所謂 nested try-catch 就是
在 try-catch 結構之中又有 try-catch
比起巢狀 if-else 或 巢狀 for 迴圈
try-catch 的程式碼更為冗長且不易閱讀
因此應盡可能避免
以下分為兩種情形:
在 try 區塊中
以 FileOutputStream 作為例子
new 和 flush 分別都要捕捉例外
可能發生以下情形
FileOutputStream out;
try {
out = new FileOutputStream("test");
try {
out.flush();
} catch (IOException e) {
}
} catch (FileNotFoundException e) {
}
這種在 try 區塊中的 try-catch 是完全可以避免掉的
只要將 catch 區塊移動到外層 try 即可
換句話說,就算有多個例外
統一只在一層 try-catch 捕捉
FileOutputStream out;
try {
out = new FileOutputStream("test");
out.flush();
} catch (FileNotFoundException e) {
} catch (IOException e) {
}
在 catch 或 finally 區塊中
典型的例子是 java.sql.Connection 物件
一旦捕捉到例外要 rollback,結束要 close
但 rollback 與 close 各自又會再拋出例外
造就這樣繁瑣的寫法
Connection connection = null;
try {
connection = DriverManager.getConnection("", "", "");
connection.commit();
} catch (SQLException e) {
if (connection != null) {
try {
connection.rollback();
} catch (SQLException e1) {
}
}
} finally {
if (connection != null) {
try {
connection.close();
} catch (SQLException e1) {
}
}
}
這種 try-catch 無法省略
只能透過 extract method 重構優化:
將 rollback 和 close 分別提取成獨立的方法
try-catch 當然連帶移去自己的方法中
這樣程式主幹就變得清晰簡潔
public void demo() {
Connection connection = null;
try {
connection = DriverManager.getConnection("", "", "");
connection.commit();
} catch (SQLException e) {
rollback(connection);
} finally {
close(connection);
}
}
public void rollback(Connection connection) {
if (connection == null) {
return;
}
try {
connection.rollback();
} catch (SQLException e1) {
}
}
public void close(Connection connection) {
if (connection == null) {
return;
}
try {
connection.close();
} catch (SQLException e) {
}
}
try-with-resources
比較簡潔的寫法
將資源放在 try 的小括弧中
一旦離開 try block 就自動 close
所以不需要 finally block
但缺點是在 catch block 中無法共用該資源
try (Connection connection = DriverManager.getConnection("", "", "");) {
connection.commit();
} catch (SQLException e) {
//connection.rollback();
}