Java 7 新特性之try-with-resources實踐理解
想像這麼一個情景,我們需要使用一個資源,在使用完之後需要關閉該資源,並且使用該資源的過程中有可能有異常拋出。此時我們都會想到用try-catch語句,在finally中關閉該資源。此時會有一個問題,如果關閉該資源的時候也拋出了異常呢?見如下例子:
package com.rundong; import java.io.IOException; public class ResourceTest implements AutoCloseable{ @Override public void close() throws IOException { throw new IOException("close Exception"); } }
package com.rundong; import java.io.IOException; import java.sql.SQLException; public class Main { public static void main(String[] args) { try { throwTest(); } catch (SQLException e) { System.out.println("catch SQLException"); e.printStackTrace(); } catch (IOException e) { System.out.println("catch IOException"); e.printStackTrace(); } } static void throwTest() throws SQLException, IOException { ResourceTest resource = null; try { resource = new ResourceTest(); throw new SQLException("the first Exception"); } catch (SQLException e) { System.out.println("catch the first Exception"); // do something throw e; } finally { if (resource != null) resource.close(); } } }
輸出結果:
發現什麼問題了嗎?
finally中拋出的異常將try中拋出的異常覆蓋了!我們無法捕獲到第一個異常!
Java 7 的解決方式:
package com.rundong; import java.io.IOException; import java.sql.SQLException; public class Main { public static void main(String[] args) { try { throwTest(); } catch (SQLException e) { System.out.println("catch SQLException"); e.printStackTrace(); } catch (IOException e) { System.out.println("catch IOException"); e.printStackTrace(); } } static void throwTest() throws SQLException, IOException { try (ResourceTest resource = new ResourceTest()) { throw new SQLException("the first Exception"); } catch (SQLException e) { System.out.println("catch the first Exception"); // do something throw e; } } }
輸出結果:
try-with-resources的寫法就能很好的處理這樣的情景,它會自動關閉資源,並且如果關閉資源時也拋出了異常,不會覆蓋原有異常的拋出。
使用條件:實現了AutoCloseable介面的類。
同時,這也提示著我們,永遠不要嘗試在finally中拋出異常!