Почему мы должны как объявлять, так и определять ресурсы в блоке try-with-resource?
try(PrintWriter f = new PrintWriter(new BufferedWriter(new FileWriter("abc.txt")));)
{}
catch(IOException ex)
{
ex.printStackTrace();
}
Выше работает отлично. Но, когда я делаю
PrintWriter f;
try(f = new PrintWriter(new BufferedWriter(new FileWriter("abc.txt")));)
{}
catch(IOException ex)
{
ex.printStackTrace();
}
Это бросает ошибки. Почему это так? Я тестировал эту новую функцию, и я придерживался мнения, что я выберу второй метод и после try-catch statement
распечатал бы ресурс PrintWriter f
- который должен быть нулевым, если оператор try-with-resource работает, как ожидалось. Почему 2-й путь не разрешен?
Также, как я мог проверить это методом 1?
3 ответа
Так как try-with-resources
на самом деле добавляет finally
заблокировать для вас, чтобы закрыть ресурсы после использования, чтобы они не могли быть использованы в любом случае (после того, как вы оставите try
блок).
Итак, этот код
try(PrintWriter f = new PrintWriter(new BufferedWriter(new FileWriter("abc.txt")));) {
} catch(IOException ex) {
ex.printStackTrace();
}
на самом деле переводится в
PrintWriter f = null;
try {
f = new PrintWriter(new BufferedWriter(new FileWriter("abc.txt")));)
// now do something
} catch(IOException ex) {
ex.printStackTrace();
}
finally {
try {
f.close();
catch(IOException ex) {}
}
}
Так что это была первоначальная цель, избавить вас от раздутого кода и позволить вам позаботиться о try
заблокировать и оставить остальное на JVM. Также посмотрите, что Oracle по этому поводу скажет.
Я полагаю, что приведенный ниже код отвечает на ваш вопрос с неожиданным результатом.
PrintWriter t = null;
try( PrintWriter f = new PrintWriter( new BufferedWriter(
new FileWriter( "abc.txt" ) ) ) ) {
f.println( "bar" );
t = f;
} catch( IOException ex ) {
ex.printStackTrace();
}
System.out.println( t );
t.println( "foo" );
t.close();
Выход:
java.io.PrintWriter@1fc4bec
Но ничего не добавляется в файл, так как автор был закрыт при попытке.
Редактировать: Если вы хотите играть с TWR, напишите класс, который реализует AutoClosable, например:
public class Door implements AutoCloseable {
public Door() {
System.out.println( "I'm opening" );
}
public void close() {
System.out.println( "I'm closing" );
}
public static void main( String[] args ) {
try( Door door = new Door() ) { }
}
}
Выход:
Я открываю
Я закрываю
Не совсем уверен, но делаю некоторые сложные предположения:
Значение f после блока catch потенциально не определено. Поэтому вам нужно будет добавить все виды проверок, чтобы проверить, был ли Объект создан, использован и / или закрыт. Но если вам нужны все эти проверки, было бы проще вообще не использовать эту идиому.
JIT может успешно оптимизировать код с помощью локальной блочной переменной.
Переменная AutoClosure не должна быть установлена на другую переменную во время блока try, но может быть впоследствии. Может быть, это слишком сложно для проверки JIT.