尝试资源详细信息
使用对象我们使用3个基本步骤:
- 宣言
- 实例化
- 初始化
我的问题是在()
部分try-with中必须完成哪些步骤才能自动关闭资源。
示例1 – 将在此代码中自动关闭FileReader对象:
try (BufferedReader br = new BufferedReader(new FileReader(filePath))) { //some code; }
示例2 – 将在此代码中自动关闭buf2:
private static BufferedReader buf1; public static void main(String[] args) throws IOException { //some code try (BufferedReader buf2 = buf1) { } }
PS有人认为这个问题与Try With Resources和Try-Catch重复。 它不是。 这个问题是关于try-catch和try-with-resources之间的区别。 我的问题是关于试用的细节。
每当需要与语言相关的细节时,最完整的参考是Java语言规范(仅限Google)。 对于try
-with-resources语句,您可以阅读第14.20.3节 ,其中声明了以下内容:
try ({VariableModifier} R Identifier = Expression ...) Block
被翻译成
{ final {VariableModifierNoFinal} R Identifier = Expression; Throwable #primaryExc = null; try ResourceSpecification_tail Block catch (Throwable #t) { #primaryExc = #t; throw #t; } finally { if (Identifier != null) { if (#primaryExc != null) { try { Identifier.close(); } catch (Throwable #suppressedExc) { #primaryExc.addSuppressed(#suppressedExc); } } else { Identifier.close(); } } } }
在第一个示例中,资源R
是BufferedReader
, Identifier
是br
, Expression
是new BufferedReader(new FileReader(filePath))
。 因此,在隐式finally
块中仅关闭BufferedReader
。 finally
块不会在FileReader
上调用close
,因为它不是资源声明本身的一部分。 但是 , BufferedReader.close()
的实现在内部调用包装的FileReader
的close
方法。 所以第一个问题的答案是肯定的,因为包装器对象关闭它(遵循资源应该在释放时释放任何包装资源的常识), 而不是因为try
-with-resources。
在第二个例子中:
private static BufferedReader buf1; public static void main(String[] args) throws IOException { //some code try (BufferedReader buf2 = buf1) { } }
答案取决于some code
。 这里buf2
和buf1
都指向内存中的同一个对象。 如果这个“某些代码”将buf1
初始化为某个对象,则该对象将被关闭,因为buf2
也引用它。 如果不是,并且buf1
为null(因此buf2
为null),则由于上面隐式finally
显示的空检查,因此不会关闭任何内容。
-
FileReader
将被关闭。 但那不是因为它在try语句中。 这是因为当BufferedReader
关闭时,它也会调用FileReader
上的close()
。 对于一个反例,我有一个名为X
的类,它实现了AutoCloseable
。 该类在其构造函数中需要一个Foo
对象。 所以我写道:try (X x = new X(new Foo())) { }
Foo
会被关闭吗? 它甚至没有实现AutoCloseable
!
-
我写了以下内容来测试这个:
BufferedReader buf1 = null; try (BufferedReader buf2 = buf1) { }
它工作得很好,没有例外! 我的猜测是,在try语句结束时,它会检查对象是否为null。 如果不是,则关闭它。 所以在这种情况下,因为buf2为null,所以无法关闭。