2015-09-06 75 views
2

使用对象,我们使用3个基本步骤:尝试与 - 资源的详细信息

  1. 宣言
  2. 实例化
  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之间的区别。我的问题是关于试用的细节。

+3

听起来像一个家庭作业问题,但这里有个提示:try-with-resources *要求*声明的变量实现'AutoCloseable',并且会在隐式finally块中调用'close()'。 – Andreas

+1

准备(学习)认证*是作业。谷歌OCPJP甚至会链接到“Oracle大学”网站。 ---也许在[The try-with-resources Statement](https://docs.oracle.com/javase/tutorial/essential/exceptions/tryResourceClose.html)上的Java教程的第一段会帮助你。 – Andreas

+1

如果你真的在认真学习Java,你不应该害怕尝试。创建一个AutoCloseable类。在close()方法中添加一个System.out.println语句。使用上面的代码而不是BufferedReader。看看是否打印了一些东西。或者只是在BufferedReader.close()中添加一个调试器断点并查看是否已达到。 –

回答

3

无论何时需要语言相关的细节,最完整的参考是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(); 
      } 
     } 
    } 
} 

在你的第一个例子中,资源RBufferedReader,则IdentifierbrExpressionnew BufferedReader(new FileReader(filePath))。因此,只有BufferedReader在隐含的finally块中关闭。 finally块不会在FileReader上调用close,因为它是而不是资源声明本身的一部分。但是,这种情况发生在BufferedReader.close()的执行内部调用close包装的FileReader的方法。所以第一个问题的答案是肯定的,因为包装器对象关闭它(遵循常见的理解,即资源在释放时应该释放任何包装的资源),而不是,因为try与资源。

在第二个例子:

private static BufferedReader buf1; 

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

    } 
} 

的答案取决于some code。这里buf2buf1都指向内存中的同一个对象。如果这个“一些代码”初始化为buf1某个对象,那么这个对象将被关闭,因为buf2也指向它。如果不是,并且buf1为空(因此buf2为空),则由于在上面示出的隐含的finally中的空检查,所以没有东西会被关闭。

1
  1. FileReader将被关闭。但那不是因为它在试验声明中。这是因为BufferedReader关闭时,FileReader也会调用close()。举一个反例,我有一个名为X的课程,它实现AutoCloseable。并且该类在其构造函数中需要一个Foo对象。所以我写:

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

Foo被关闭?它甚至没有执行AutoCloseable

  • 我写了下面对此进行测试:

    BufferedReader buf1 = null; 
    try (BufferedReader buf2 = buf1) { 
    
    } 
    
  • 和它的工作完全正常,没有例外!我的猜测是,在try语句结束时,它检查对象是否为空。如果不是,则关闭它。所以在这种情况下,因为buf2为空,所以不能关闭。