Используйте Try-With-Resources вместо блока finally, когда несколько строк в блоке try вызывают исключение

Фрагмент кода:

InputStream inputStream = null;
try{
    ExternalServiceObject object = externalService.getObject();
    inputStream = object.getInputStream();
    // further uses of inputStream
 } catch(Exception e){
   throw e;
  } finally {
        if(inputStream != null)
           inputStream.close();
  }

Здесь externalService.getObject() также может генерировать исключение.

Хотите реорганизовать этот код, используя try-with-resources, избегая, таким образом, блока finally. Или текущее поведение является наиболее подходящим поведением.

Все комментарии и ответы приветствуются.


person Kartavya Ramnani    schedule 05.01.2018    source источник
comment
Если ваш вопрос касается того, будет ли обработано исключение, созданное внутри части объявления ресурса try-with-resources, то ответ - да. Вы можете попробовать это на относительно простом примере — сделайте так, чтобы ваш externalService.getObject() выдавал какое-то исключение и проверял, выполняется ли блок catch.   -  person Igor Nikolaev    schedule 06.01.2018
comment
Да, это часть вопроса. Помогли мне понять попытку с ресурсами. Спасибо большое.   -  person Kartavya Ramnani    schedule 06.01.2018


Ответы (4)


Если вам не нужен объект внешней службы для чего-либо еще:

try (InputStream inputStream = externalService.getObject().getInputStream()) {
    // further uses of inputStream
} catch (Exception e) {
    // ... logging etc
    throw e;
}
person AJNeufeld    schedule 05.01.2018
comment
Превосходно ! Элегантное решение :') Большое спасибо. - person Kartavya Ramnani; 06.01.2018

Я считаю, что порядок выполнения в try-with-resources сверху вниз (как и все другие определения переменных java)

try
(
    ExternalServiceObject externalServiceObject = externalService.getObject(),
    InputStream inputStream = externalServiceObject.getInputStream();
)
{
    // further uses of inputStream
}
catch (Exception e)
{
    // do stuff.
}

Предупреждение: ExternalServiceObject должен реализовывать AutoCloseable

person DwB    schedule 05.01.2018
comment
+1 за отличное предостережение. Внешний сервис — AWS S3Client, хотел бы я отметить их здесь. - person Kartavya Ramnani; 06.01.2018

Итак, используйте try-with-resources, если это то, что вы хотите использовать:

try {
  ExternalServiceObject object = externalService.getObject();
  try (InputStream inputStream = object.getInputStream()) {
    // ...
  }
} catch (Exception e) {
  throw e; // But why catch it only to rethrow?
}
person Andy Turner    schedule 05.01.2018
comment
Разве наличие блока try внутри блока try не сделает код немного загроможденным? И извините, после отлова исключения делается логирование и записываются метрики, но мне было лень все это дело добавлять. Спасибо большое. - person Kartavya Ramnani; 06.01.2018
comment
выглядеть немного загроможденным Если это то, что вам нужно, то это то, что вам нужно. - person Andy Turner; 06.01.2018
comment
Этот код не закрывает автоматически файл ExternalServiceObject. - person Basil Bourque; 06.01.2018
comment
@ Василий, как и ОП. Вопрос не дает понять, что его нужно закрыть. - person Andy Turner; 06.01.2018

Закрытие InputStream можно выполнить с помощью блока try-with-resources. Это более читабельно и менее громоздко. InputStream реализует AutoCloseable, поэтому при выходе из блока try-with-resources автоматически вызывается метод закрытия класса. Если вы используете InputStream только для блока try-catch-finally, вам следует переместить его в блок try.

Кроме того, вам следует избегать (где это возможно) перехвата Exception. Любые результирующие исключения, выброшенные в блоке try, могут привести к нежелательному поведению.

person SirCipher    schedule 05.01.2018