有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java trywithresources详细信息

使用对象时,我们使用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)
    {

    } 
 }

旁白:有人认为这个问题是Try With Resources vs Try-Catch的重复。事实并非如此。这个问题是关于try-catch和try-with-resources之间的区别。我的问题是关于试用的细节


共 (2) 个答案

  1. # 1 楼答案

    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是空的,所以它不能被关闭

  2. # 2 楼答案

    每当需要与语言相关的细节时,最完整的参考就是Java语言规范(只需谷歌一下)。对于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,资源Identifierbr,资源Expressionnew BufferedReader(new FileReader(filePath))。因此,隐式finally块中只有BufferedReader是闭合的。finally块不会调用FileReader上的close,因为它不是资源声明本身的一部分然而BufferedReader.close()的实现在内部调用包装的FileReaderclose方法。因此,第一个问题的答案是肯定的,因为包装器对象关闭了它(遵循资源在释放时应该释放任何包装好的资源的普遍智慧),而不是,因为try-有资源

    在第二个例子中:

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

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