尝试资源详细信息[重复]
Posted
技术标签:
【中文标题】尝试资源详细信息[重复]【英文标题】:try-with-resources details [duplicate] 【发布时间】:2015-09-06 11:27:09 【问题描述】:我们使用 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)
附:有人认为这个问题与 Try With Resources vs Try-Catch 重复。它不是。这个问题是关于 try-catch 和 try-with-resources 之间的区别。我的问题是关于试用的细节。
【问题讨论】:
听起来像是一道作业题,但这里有一个提示:try-with-resources 要求声明的变量实现AutoCloseable
,并隐式调用close()
终于阻塞了。
准备(学习)认证是功课。谷歌搜索 OCPJP 甚至会链接到“甲骨文大学”网站。 --- 也许The try-with-resources Statement 上的 Java 教程的第一段会对你有所帮助。
如果你真的很想学习 Java,你不应该害怕尝试。创建一个 AutoCloseable 类。在 close() 方法中添加 System.out.println 语句。将上述代码与该类一起使用,而不是 BufferedReader。看看有没有打印出来。或者只是在 BufferedReader.close() 中添加一个调试器断点,看看是否到达。
@JB Nizet 感谢您抽出宝贵时间。我不害怕。问题是我更喜欢理解原则而不是任何情况。我写在这里是因为我希望有人能给出自动关闭的主要原则。
【参考方案1】:
只要需要语言相关的详细信息,最完整的参考就是 Java 语言规范(只需 Google 即可)。对于try
-with-resources 声明,您可以阅读section 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))
。因此,只有BufferedReader
在隐式finally
块中被关闭。 finally
块不会在 FileReader
上调用 close
,因为它不是资源声明本身的一部分。 然而,BufferedReader.close()
的实现会在内部调用包装好的FileReader
的close
方法。所以第一个问题的答案是肯定的,因为包装对象关闭了它(遵循资源在释放自身时应该释放任何包装资源的常识),不是因为try
-有资源。
在第二个例子中:
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
为空(因此buf2
为空),则不会关闭任何内容,因为上面显示的隐式finally
中的空检查。
【讨论】:
【参考方案2】: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 语句的末尾,它会检查对象是否为空。如果不是,则关闭它。所以在这种情况下,由于 buf2 为 null,所以无法关闭。
【讨论】:
以上是关于尝试资源详细信息[重复]的主要内容,如果未能解决你的问题,请参考以下文章
异步 - 等待 JavaScript:无法从错误对象中捕获错误详细信息 [重复]
使用未经检查或不安全的操作,使用 -Xlint 重新编译:未检查详细信息 [重复]