оператор try-with-resources в Java

В этом примере программы Java:

package test;

import java.sql.DriverManager;
import java.sql.Connection;
import java.sql.Statement;

public class Test
{
    private static void example(){
        String url = "jdbc:oracle:thin:@//localhost:7856/xe";
        String user = "user";
        String password = "pass";
        try(Connection con = DriverManager.getConnection(url, user, password);
            Statement stmt = con.createStatement()){
            throw new OutOfMemoryError("Error");
        }catch (SQLException e){
            System.err.println("SQLException");
        }
    }

    public static void main(String [] args){
        try{
            example();
        }catch (OutOfMemoryError e){
            System.err.println("OutOfMemoryError");
        }
        // Rest of code here...
    }
}

Когда в теле статического метода example() выдается ошибка OutOfMemoryError, соединение "con" и оператор "stmt" автоматически закрываются перед завершением статического метода example(), несмотря на отсутствие какой-либо "уловки", которая улавливает эти ошибка, так что остальная часть кода в main() уверена, что эти два объекта закрыты?

Спасибо.


person user3645667    schedule 16.05.2014    source источник


Ответы (1)


Да; конструкция try-with-resources всегда закрывает ресурс, даже если это непроверенный бросок (например, OutOfMemoryError).

Это указано в JLS 14.20. 3, который начинается с довольно общего заявления о том, что ресурсы «закрываются автоматически», но затем переходит к различным примерам времени, когда ресурс закрывается. По сути, любой ресурс, отличный от null, всегда закрыт, как если бы закрытие было в предложении finally в try-finally, созданном только для этого одного ресурса. Это так, даже если в try есть несколько ресурсов, как в вашем случае ("Исключение из закрытия одного ресурса не препятствует закрытию других ресурсов").

Простой класс, чтобы продемонстрировать это:

public class Twr {
  private static class TwrCloseable implements AutoCloseable {
    private final String id;

    TwrCloseable(String id) {
      this.id = id;
    }

    @Override
    public void close() {
      System.out.println("closing " + id);
    }
  }

  public static void main(String[] args) {
    try (TwrCloseable closeable1 = new TwrCloseable("first");
         TwrCloseable closeable2 = new TwrCloseable("second")) {
      throw new OutOfMemoryError();
    }
  }
}

Выход:

closing second
closing first
Exception in thread "main" java.lang.OutOfMemoryError
    at Twr.main(Twr.java:19)

Обратите внимание, что они закрываются в обратном порядке; «второй» закрывается перед «первым». В вашем примере это означает, что Statement закрывается перед Connection, а это именно то, что вы хотите.

person yshavit    schedule 16.05.2014