try-finally 和 try-catch-finally 語句
try...catch...finally
語句將異常處理與清理程式碼結合在一起。finally
塊包含將在所有情況下執行的程式碼。這使它們適用於資源管理和其他型別的清理。
嘗試,終於
這是一個更簡單(try...finally
)形式的例子:
try {
doSomething();
} finally {
cleanUp();
}
try...finally
的行為如下:
- 執行
try
塊中的程式碼。 - 如果
try
塊沒有丟擲異常:- 執行
finally
塊中的程式碼。 - 如果
finally
塊丟擲異常,則傳播該異常。 - 否則,控制傳遞到
try...finally
之後的下一個語句。
- 執行
- 如果 try 塊中丟擲了異常:
- 執行
finally
塊中的程式碼。 - 如果
finally
塊丟擲異常,則傳播該異常。 - 否則,原始異常繼續傳播。
- 執行
finally
塊中的程式碼將始終執行。 (唯一的例外是如果呼叫 System.exit(int)
,或者如果 JVM 發生混亂。)因此,finally
塊是始終需要執行的正確位置程式碼; 例如關閉檔案和其他資源或釋放鎖。
try-catch-終於
我們的第二個例子展示了 catch
和 finally
如何一起使用。它還說明清理資源並不簡單。
// This code snippet writes the first line of a file to a string
String result = null;
Reader reader = null;
try {
reader = new BufferedReader(new FileReader(fileName));
result = reader.readLine();
} catch (IOException ex) {
Logger.getLogger.warn("Unexpected IO error", ex); // logging the exception
} finally {
if (reader != null) {
try {
reader.close();
} catch (IOException ex) {
// ignore / discard this exception
}
}
}
在這個例子中,try...catch...finally
的一整套(假設的)行為太複雜了,不能在這裡描述。簡單的版本是 finally
塊中的程式碼將始終執行。
從資源管理的角度來看這個:
- 我們在
try
塊之前宣告資源(即reader
變數),以便它將在finally
塊的範圍內。 - 通過放置
new FileReader(...)
,catch
能夠處理開啟檔案時丟擲的任何IOError
異常。 - 我們需要在
finally
塊中使用reader.close()
,因為我們無法在try
塊或catch
塊中攔截一些異常路徑。 - 但是,由於在初始化
reader
之前可能會丟擲異常,我們還需要一個明確的null
測試。 - 最後,
reader.close()
呼叫可能(假設)丟擲異常。我們並不關心這一點,但如果我們不在源頭捕獲異常,我們需要在呼叫堆疊中進一步處理它。
Version >= Java SE 7
Java 7 及更高版本提供了另一種 try-with-resources 語法 ,可顯著簡化資源清理。