尝试资源详细信息

使用对象我们使用3个基本步骤:

  1. 宣言
  2. 实例化
  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(); } } } } 

在第一个示例中,资源RBufferedReaderIdentifierbrExpressionnew BufferedReader(new FileReader(filePath)) 。 因此,在隐式finally块中仅关闭BufferedReaderfinally块不会在FileReader上调用close ,因为它不是资源声明本身的一部分。 但是BufferedReader.close()的实现在内部调用包装的FileReaderclose方法。 所以第一个问题的答案是肯定的,因为包装器对象关闭它(遵循资源应该在释放时释放任何包装资源的常识), 而不是因为try -with-resources。

在第二个例子中:

 private static BufferedReader buf1; public static void main(String[] args) throws IOException { //some code try (BufferedReader buf2 = buf1) { } } 

答案取决于some code 。 这里buf2buf1都指向内存中的同一个对象。 如果这个“某些代码”将buf1初始化为某个对象,则该对象将被关闭,因为buf2也引用它。 如果不是,并且buf1为null(因此buf2为null),则由于上面隐式finally显示的空检查,因此不会关闭任何内容。

  1. FileReader将被关闭。 但那不是因为它在try语句中。 这是因为当BufferedReader关闭时,它也会调用FileReader上的close() 。 对于一个反例,我有一个名为X的类,它实现了AutoCloseable 。 该类在其构造函数中需要一个Foo对象。 所以我写道:

     try (X x = new X(new Foo())) { } 

Foo会被关闭吗? 它甚至没有实现AutoCloseable

  1. 我写了以下内容来测试这个:

     BufferedReader buf1 = null; try (BufferedReader buf2 = buf1) { } 

它工作得很好,没有例外! 我的猜测是,在try语句结束时,它会检查对象是否为null。 如果不是,则关闭它。 所以在这种情况下,因为buf2为null,所以无法关闭。