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)


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

Изявлението 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. Идвам от C# фон и използвах 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 Language Specification 14.20.3). Същото се случва и за java.sql.Connection. Не знам със сигурност кое е правилно, но вярвам, че грешката е скрита или игнорирана. - person Karl Henselin; 23.06.2017
comment
@KarlHenselin прав си, изключението ще бъде премахнато. Мисълта ми беше, че понякога искате да обработите такова изключение и с помощта на този синтаксис няма да ви бъде позволено да го направите :) Ще редактирам отговора, за да бъде по-конкретен. Благодаря! - person Maciej Dobrowolski; 24.06.2017