try-finally с закрытым автоматическим рефакторингом для try-with-resources с codestyle/checkstyle

Я работаю над кодовой базой, которая недавно перешла с Java 6 на Java 7. Я хотел бы заменить такие конструкции:

Connection conn = null;
try{
    conn = new Connection();
    ...
} catch(Exception ex){
    ...
} finally{
    if (conn != null){
        conn.close();
    }
}

с try-with-resources (доступно начиная с Java 1.7):

try(Connection conn = new Connection()){
    ...
} catch(Exception ex){
    ...
}

Существует ли автоматизированный способ автоматического преобразования старого в новое (возможно, с помощью плагина Checkstyle или внутри самого Eclipse)?


person Kevin Cruijssen    schedule 26.02.2016    source источник


Ответы (1)


Было бы трудно изменить все это быстро. Обратите внимание, что иногда в блоке finally есть еще один блок try-catch, который перехватывает исключения, возникающие при закрытии ресурса.

Оператор try-with-resources позволяет обрабатывать исключения закрытия ресурсов (исключения, созданные в методе close, будут подавлены).

Я не слышал о такой Eclipse функции, но если вы хотите использовать IntelliJ IDEA Community Edition IDE только для этой цели.

#1

Вы можете использовать функции проверки кода, которые называются:

  1. 'try finally' replaceable with 'try' with resources.
  2. AutoCloseable used without 'try' with resources

Вам нужно просто нажать Ctrl+Alt+Shift, написать название проверки и нажать Enter. После этого вы увидите места, где IDEA может применить этот шаблон, но имейте в виду, что он не покрывает 100% случаев.

#2

Другой способ, более сложный, но сильно настраиваемый — это Structural Search and Replace функциональность. Вы можете определить там структуру, которая должна быть изменена:

try {
    $type$ $objectName$ = new $concreteType$($args$)
    $tryStatements$;
} catch($exceptionType$ $exceptionName$) {
    $catchStatements$;
} finally {
    $finallyStatements$;
}

И финальная структура:

try ($type$ $objectName$ = new $concreteType$($args$)) {
  $tryStatements$;
} catch($exceptionType$ $exceptionName$) {
    $catchStatements$;
}

В настройках переменных можно указать, что $concreteType$ реализует AutoCloseable интерфейс.

Но обратите внимание, что:

  1. Здесь я избавляюсь от блока finally и поддерживаю один блок catch.
  2. Также предполагается, что на один блок try-with-resources будет открыт один ресурс.
  3. Как упоминалось ранее, в блоке finally нет обработки исключений.

Этот шаблон, безусловно, требует дополнительной работы, и, возможно, это не стоит делать.

person Maciej Dobrowolski    schedule 26.02.2016
comment
Ну, я тоже, если честно, знал об IntelliJ. Я исхожу из фона С# и использовал ReSharper в Visual Studio. Позже я узнал, что IntelliJ создан теми же производителями, что и ReSharper, поэтому у них много схожих функций. К сожалению, проект, над которым я сейчас работаю, находится в Eclipse. Это, очевидно, не является главным приоритетом, но я подумал, что если есть что-то простое, чтобы изменить все это одновременно, было бы неплохо. Поскольку его нет, мы просто изменим его, когда наткнемся на старый try-close_in_finally, и, возможно, однажды найдем их все, чтобы изменить их одновременно. Спасибо - person Kevin Cruijssen; 29.02.2016
comment
@KevinCruijssen вашему проекту даже не нужно компилировать/работать с IntelliJ. Вы можете просто импортировать его туда, выполнить замену, сохранить файлы и вернуться в Eclipse. - person Maciej Dobrowolski; 29.02.2016
comment
Хорошая точка зрения. Скоро установим IntelliJ и сделаю замены. На моей текущей работе мы используем вечер пятницы для всех видов вещей, не связанных с проектом, таких как рефакторинг, покрытие кода новыми модульными тестами, обмен проблемами / новыми вещами, с которыми мы столкнулись, и т. д. Пока я приму ваш ответ. Еще раз спасибо. - person Kevin Cruijssen; 29.02.2016
comment
Меня немного смущает одна строка, которую вы сказали: оператор try-with-resources не перехватывает исключения закрытия ресурсов. Но на странице stackoverflow.com/questions/ 17739362/ говорит, и close() вызывается автоматически, если он генерирует исключение IOException, оно будет подавлено (как указано в Спецификации языка Java 14.20.3). То же самое происходит и с java.sql.Connection. Я точно не знаю, что правильно, но я считаю, что ошибка подавляется или игнорируется. - person Karl Henselin; 23.06.2017
comment
@KarlHenselin, вы правы, исключение будет подавлено. Я хотел сказать, что иногда вы хотите обработать такое исключение, и с помощью этого синтаксиса вам не разрешат это сделать :) Я отредактирую ответ, чтобы он был более конкретным. Спасибо! - person Maciej Dobrowolski; 24.06.2017