попробуйте с ресурсом, будет ли ресурс очищаться, если выброшенное исключение не будет перехвачено?

Что происходит, когда попытка использования ресурса вызывает исключение, которое перехватывается снаружи? Будет ли еще проводиться очистка?

Образец:

public void myClass() throws customException {
  try (Connection conn = myUtil.obtainConnection()) {
     doSomeStuff(conn);
     if (someCheck)
       throw new customException(somePara);

     doSomeMoreStuff(conn);
     conn.commit();

  } catch (SQLException e) {
     log.error(e);
  }
}

Меня больше всего интересует, когда выбрасывается customException. Я не ловлю это исключение с помощью улова моей попытки с ресурсом. Поэтому мне интересно, будет ли выполняться очистка соединения в этом сценарии.

Или мне нужно поймать и перебросить соединение, например:

public void myClass() throws customException {
  try (Connection conn = myUtil.obtainConnection()) {
     doSomeStuff(conn);
     if (someCheck)
       throw new customException(somePara);

     doSomeMoreStuff(conn);
     conn.commit();

  } catch (SQLException e) {
     log.error(e);
  } catch (customException e) {
     throw new customException(e);
  }
}

person Community    schedule 28.08.2019    source источник
comment
Да, будет вызван метод close() ресурса, независимо от того, поймаете вы исключение или нет. Нет необходимости перехватывать и повторно выбрасывать исключение.   -  person Jesper    schedule 28.08.2019
comment
в вашем втором примере не будет ли зацикливаться между catch и throw new ? плюс, когда вы пытаетесь использовать ресурсы, вам не нужно закрывать поток вручную close() будет вызываться автоматически   -  person Phill Alexakis    schedule 28.08.2019
comment
@PhillAlexakis Нет, это не вызовет бесконечный цикл между catch и throw new, потому что throw не находится внутри блока try.   -  person Jesper    schedule 28.08.2019
comment
@Джеспер, хорошо   -  person Phill Alexakis    schedule 28.08.2019
comment
На самом деле вам не нужно ретро исключение, вам вообще не нужно его ловить. Нет необходимости ни в блоке catch, ни в блоке finally в atry-with-resources.   -  person daniu    schedule 28.08.2019


Ответы (2)


Да, очистка произойдет... если метод close() правильно обрабатывает очистку:

Пример исполнения

public class Main {
  public static void main(String[] args) throws Exception {
    try (AutoCloseable c = () -> System.out.println("close() called")) {
      throw new Exception("Usual failure");
    }
  }
}

(сокращено Хольгером в комментариях)

Вывод на стандартный вывод:

close() called

Вывод на стандартный вывод:

Exception in thread "main" java.lang.Exception: Usual failure
    at Main.main(Main.java:4)

Пример выполнения с исключением, выброшенным в методе close()

(предложено Хольгером в комментариях)

public class Main {
  public static void main(String[] args) throws Exception {
    try (AutoCloseable c = () -> { throw new Exception("Failure in the close method"); }) {
      throw new Exception("Usual failure");
    }
  }
}

Нет вывода на стандартный вывод.

Вывод на стандартный вывод:

Exception in thread "main" java.lang.Exception: Usual failure
    at Main.main(Main.java:4)
    Suppressed: java.lang.Exception: Failure in the close method
        at Main.lambda$main$0(Main.java:3)
        at Main.main(Main.java:3)
person Olivier Grégoire    schedule 28.08.2019

В документации есть ответ на ваш точный вопрос

Примечание. Оператор try-with-resources может иметь блоки catch и finally, как и обычный оператор try. В операторе try-with-resources любой блок catch или finally запускается после закрытия объявленных ресурсов.

Если из блока try выдается исключение, а из оператора try-with-resources выдается одно или несколько исключений, то эти исключения, выдаваемые из оператора try-with-resources, подавляются, и блоком выдается исключение. который вызывается методом writeToFileZipFileContents. Вы можете получить эти подавленные исключения, вызвав метод Throwable.getSuppressed из исключения, созданного блоком try.

Пожалуйста, посмотрите https://docs.oracle.com/javase/tutorial/essential/exceptions/tryResourceClose.html

person phil_g    schedule 28.08.2019
comment
Да и нет. Я проверил документы, но на самом деле не понял утверждения. Причиной было некоторое непонимание концепции попытки с ресурсом, которая была разъяснена в другом ответе. Теперь это действительно имеет смысл - person ; 28.08.2019
comment
Почему кто-то понизил этот ответ? Этот ответ такой же правильный, как и мой! - person Olivier Grégoire; 29.08.2019