使用对象我们使用3个基本步骤:
我的问题是在()
尝试的部分必须完成哪些步骤才能自动关闭资源。
示例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)
{
}
}
P.S。有人认为这个问题与Try With Resources vs Try-Catch重复。它不是。这个问题是关于try-catch和try-with-resources之间的区别。我的问题是关于试用的细节。
答案 0 :(得分:5)
每当需要与语言相关的详细信息时,最完整的参考是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
数据块不会在close
上调用FileReader
,因为不是资源声明本身的一部分。 但,恰好BufferedReader.close()
的实施内部调用了包裹的close
的{{1}}方法。所以第一个问题的答案是肯定的,因为包装器对象关闭它(遵循资源应该在自身释放时释放任何包装资源的常识), not 因为{{1} } -with资源。
在第二个例子中:
FileReader
答案取决于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
中的空检查,所以不会关闭任何内容。
答案 1 :(得分:1)
FileReader
将被关闭。但那不是因为它在try语句中。这是因为当BufferedReader
关闭时,它也会在close()
上调用FileReader
。对于一个反例,我有一个名为X
的类,它实现了AutoCloseable
。该类在其构造函数中需要一个Foo
对象。所以我写道:
try (X x = new X(new Foo())) {
}
Foo
会被关闭吗?它甚至没有实现AutoCloseable
!
我写了以下内容来测试这个:
BufferedReader buf1 = null;
try (BufferedReader buf2 = buf1) {
}
它工作得很好,没有例外!我的猜测是,在try语句的末尾,它检查对象是否为null。如果不是,则关闭它。所以在这种情况下,因为buf2为空,所以它不能被关闭。