1. 程式人生 > >JDK 8 try-with-resource的問題

JDK 8 try-with-resource的問題

JDK 7 中支援try-with-resource,對其中資源進行自動關閉,一直沒用過,欲學習下,以便簡化程式碼,檢視文章1,文章中有說到:因為編譯時編譯器會自動幫程式碼加上finally並呼叫close方法(前提是這些資源類都實現了Closeable介面)。(將你編譯好的.class檔案拖入idea即可看到編譯後的程式碼(idea可以反編譯出來))

簡單列一下書寫格式:

try(資源定義){       // 在try後增加括號,括號中new資源物件
   業務邏輯            // 業務邏輯程式碼中也可以建立資源物件,這樣也能自動關閉
} 

但在JDK8中寫例子時遇到一個奇怪問題,測試例子原始碼如下

public class TestARM {

    public static void main(String[] args){

        test();
        System.out.println("test"); 
    }
    
    public static void test() {
                
        try (FileOutputStream out = new FileOutputStream(new File("D:/jdk8.txt"))) {
            
            @SuppressWarnings("resource")
            FileInputStream in = new FileInputStream(new File("D:/jdk8.txt"));
            
            in.available();
        }
        catch (FileNotFoundException e) {
            e.printStackTrace();
        }
        catch (IOException e) {
            e.printStackTrace();
        }
    }

}

編譯後的效果:

public class TestARM
{
  public static void main(String[] args)
  {
    test();
    System.out.println("test");
  }
  
  public static void test()
  {
    try
    {
      Object localObject1 = null;Object localObject4 = null;
      Object localObject3;
      label85:
      try
      {
        out = new FileOutputStream(new File("D:/jdk8.txt"));        
      }
      finally
      {
        FileOutputStream out;        // 為什麼out變數的宣告在初始化之後?
        FileInputStream in;
        localObject3 = localThrowable;
        break label85;   
        if (localObject3 != localThrowable) {
          localObject3.addSuppressed(localThrowable);
        }
      }
    }
    catch (FileNotFoundException e)
    {
      e.printStackTrace();
    }
    catch (IOException e)
    {
      e.printStackTrace();
    }
  }
}

並沒有顯示的表現在finally中有關閉in和out的程式碼,try-with-resource沒有得到顯示。並沒有如文章1所說。

另外在另一篇文章中文章2又說到:try-with-resources 是 JDK 7 中一個新的異常處理機制,它能夠很容易地關閉在 try-catch 語句塊中使用的資源。所謂的資源(resource)是指在程式完成後,必須關閉的物件。try-with-resources 語句確保了每個資源在語句結束時關閉。所有實現了 java.lang.AutoCloseable 介面(其中,它包括實現了 java.io.Closeable 的所有物件),可以使用作為資源。

是隻能關閉實現了AutoCloseable 介面的嗎?

為此寫下測試例子:
資源類ResourceClass:

public class ResourceClass implements AutoCloseable {
    @Override
    public void close() throws Exception {
        System.out.println("Close ResourceClasss");
        
    }
}

主類:

public class TestARM2 {

    /**
     * @param args
     */
    public static void main(String[] args) {

        test();
    }

    public static void test() {
        
        try (ResourceClass resource = new ResourceClass()) {
            
            System.out.println("resource created");
        }
        catch (Exception e) {
            e.printStackTrace();
        }
        
    }

}

執行結果:

resource created
Close ResourceClasss

可以看到實現了AutoCloseable介面的資源被自動關閉了,那麼檢視下這兩個類的反編譯結果:
資源類ResourceClass:

public class ResourceClass

      implements AutoCloseable
    {
      public void close()
        throws Exception
      {
        System.out.println("Close ResourceClasss");
      }
    }

主類:

public class TestARM2
{
  public static void main(String[] args) {}
  
  public static void test()
  {
    try
    {
      Object localObject1 = null;Object localObject4 = null;
      Object localObject3;
      label62:
      try
      {
        resource = new ResourceClass();
      }
      finally
      {
        ResourceClass resource;
        localObject3 = localThrowable;
        break label62;
        if (localObject3 != localThrowable) {
          localObject3.addSuppressed(localThrowable);
        }
      }
    }
    catch (Exception e)
    {
      e.printStackTrace();
    }
  }
}

依然沒有文章1中所說的新增到將close方法新增至finally塊中。

記錄下,如果哪位同學有答案,請賜教,謝謝

建議使用try-with-resource時配合AutoCloseable介面封裝資源