2010-10-11 63 views
5

我傾向於寫代碼如下所示的很多:如何簡化/重用這個異常處理代碼

BufferedWriter w = null; // Or any other object that throws exceptions and needs to be closed 
try { 
    w = new BufferedWriter(new FileWriter(file)); 
    // Do something with w 
} catch (IOException e) { 
    e.printStackTrace(); 
} finally { 
    if (w != null) { 
     try { 
      w.close(); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } 
    } 
} 

,通常需要拋出異常,需要關閉,對象和關閉它也可能拋出異常。

我想知道上面的代碼是否可以簡化或以任何方式重用。

+0

我學習了很多的Java感謝這個問題。 :D – hpique 2010-10-11 20:11:22

回答

5

我通常會將finally塊的內容放入幫助程序中。像這樣

void close(Closeable c) { 
    if (c != null) { 
     try { 
      c.close(); 
     } catch (IOException e) { 
      // perform logging or just ignore error 
     } 
    } 
} 

Closeable接口由許多類(輸入流,數據庫連接等)來實現,所以這是有點通用的幫手。

+0

哦!像Closeable這樣的東西正是我所期待的。 – hpique 2010-10-11 14:53:24

0

寫它的方法...

BuffereWriter getMyWriter() 
{ 

// your code.... 

return w; 
} 
4

是,由於Java 1.5有一個可關閉的接口。您可以有一個關閉任何可關閉類型的靜態方法。

public static void closeIO(Closeable closeable){ 
     if (closeable != null) { 
     try { 
      closeable.close(); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } 
    } 
} 
+1

或重複使用來自番石榴的'Closeables'。 – whiskeysierra 2010-10-11 15:31:21

0

模板方法圖案這裏可以應用:

public class FileTemplate { 
    public void write(File file, WriteCallback c) { 
     BufferedWriter w = null; // Or any other object that throws exceptions and needs to be closed 
     try { 
      w = new BufferedWriter(new FileWriter(file)); 
      c.writeFile(w); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } finally { 
      if (w != null) { 
       try { 
        w.close(); 
       } catch (IOException e) { 
        e.printStackTrace(); 
       } 
      } 
     } 
    } 
} 

public interface WriteCallback { 
    public void writeFile(BufferedWriter w) throws IOException; 
} 

new FileTemplate().write(file, new WriteCallback() { 
    public void writeFile(BufferedWriter w) { ... } 
}); 
1

我傾向於與其他人誰提供服用Closeable的方法達成一致,但由於maintining很長住計劃,我用的解決方案略有不同。基本上它需要一個OutputStream來提供靈活性。

public class IOHandler { 

    private IOHandler(); 

    public static void close(OutputStream out, Closeable c) { 
    if (c != null) { 
     try { 
     c.close(); 
    } catch (IOException e) { 
     out.print(c.printStackTrace().getBytes()); 
    } 
    } 

} 

這樣做的主要好處是,你可以把它在多種方式,不再需要專門的工具來處理日誌記錄異常到stderr,stdout和文件。

IOHandler.close(System.out, openFile); 
IOHandler.close(System.err, openFile); 
IOHandler.close(logFile, openFile); 

除了這一個增加的功能,它基本上是其他人提供的相同的解決方案。

3

Java 7正在嘗試資源支持。查看this瞭解更多信息。

我引用了相關的文字和代碼示例這裏:

在Java 7中的新的嘗試,與資源的語言功能,有效申報的流參數作爲嘗試,構造的一部分,和編譯器會生成代碼,爲您自動管理這些資源。

private static void customBufferStreamCopy(File source, File target) { 
    try (InputStream fis = new FileInputStream(source); 
     OutputStream fos = new FileOutputStream(target)){ 

     byte[] buf = new byte[8192]; 

     int i; 
     while ((i = fis.read(buf)) != -1) { 
      fos.write(buf, 0, i); 
     } 
    } 
    catch (Exception e) { 
     e.printStackTrace(); 
    } 
} 
+0

+1更多分享在JDK 7 – 2010-10-11 15:07:08

+1

確定的最新變化,但也許他並不想等到2011年中期使用JDK 1.7,不是嗎? – romaintaz 2010-10-11 15:38:29

+0

我相信任何客戶都會明白。 :P – hpique 2010-10-11 16:11:34

1

我發現通常最好不要嘗試捕捉並最終全部在同一個塊中。有一個try-catch塊和一個單獨的try-finally塊通常會更好。

try { 
    BufferedWriter w = new BufferedWriter(new FileWriter(file)); // Or any other object that throws exceptions and needs to be closed 
    try { 
     // Do something with w 
    } finally { 
     w.close(); 
    } 
} catch (IOException e) { 
    e.printStackTrace(); 
} 

這也避免了任何需要空檢查W上。

+0

當基礎流仍被創建時,您會遇到問題,但外部流會在構造函數中引發異常。然後底層流不會關閉。 – 2011-08-22 15:41:05

+0

@致命'新的BufferedWriter(作家)'不會拋出任何檢查的異常。即使做了,在調用'新的BufferedWriter存在問題(新的FileWriter(文件))'由問題描述,而不是處理異常此方法。爲了緩解,你必須將'New FileWriter'分配給一個單獨的變量並關閉它。 – ILMTitan 2011-08-22 18:16:24

+0

你對BufferedWriter是正確的,但是這裏的主題更一般,你的建議也是非常一般的。由於'close()'契約,您不必分配和關閉FileWriter。 hgpc在他的開場白中做得很對。就像我知道的Apache Commons所有常見庫一樣 - 而不是偶然。所以接受的答案是最好的 - 它只是改善了正確的做法並減少了樣板。這裏沒什麼我會推薦的,即使它在這裏可能適用於這種特殊情況。 – 2011-08-22 18:48:52

6

如果你不想寫代碼在finally塊關閉,你應該看看Project Lombok

而不是寫正常

public class CleanupExample { 
    public static void main(String[] args) throws IOException { 
    InputStream in = new FileInputStream(args[0]); 
    try { 
    OutputStream out = new FileOutputStream(args[1]); 
    try { 
     byte[] b = new byte[10000]; 
     while (true) { 
     int r = in.read(b); 
     if (r == -1) break; 
     out.write(b, 0, r); 
     } 
    } finally { 
     out.close(); 
     } 
    } finally { 
    in.close(); 
    } 
    } 
} 

隨着龍目島,你可以寫

public class CleanupExample { 
    public static void main(String[] args) throws IOException { 
    @Cleanup InputStream in = new FileInputStream(args[0]); 
    @Cleanup OutputStream out = new FileOutputStream(args[1]); 
    byte[] b = new byte[10000]; 
    while (true) { 
     int r = in.read(b); 
     if (r == -1) break; 
     out.write(b, 0, r); 
    } 
    } 
} 

更可讀,和它產生關閉流的正確的方法。這適用於所有的Closeable接口

+2

+1引入lambok(我) – chedine 2010-10-11 18:38:03

+0

龍目島非常適合樣板代碼 – 2010-10-12 17:35:27