1 OutputStreamWriter out = ...
2 java.sql.Connection conn = ...
3 try {
4 Statement stat = conn.createStatement();
5 ResultSet rs = stat.executeQuery("select uid, name from user");
6 while (rs.next()) {
7 out.println("ID:" + rs.getString("uid") + ",姓名:" + rs.getString("name"));
8 }
9 conn.close();
10 out.close();
11 } catch (Exception ex) {
12 ex.printStackTrace();
13 }
程式碼第 11-13 行。捕獲例外卻僅列印堆疊追蹤,不做任何處理。printStackTrace 僅適合除錯階段,正式環境應採取:修正問題、通知相關人員、轉換為應用層例外、或重新拋出。若無法處理,不要捕獲,讓上層或 JVM 處理。
第 11 行 catch (Exception ex)。等同捕獲幾乎所有例外,導致 JDBC SQLException 與 I/O IOException 混雜處理。應分別捕獲具體例外類型,必要時使用多 catch 區塊;不預期的例外讓其向上傳播。
第 3-10 行。若第 5-8 行拋出例外,conn.close()、out.close() 不會執行,造成資源洩漏。必須使用 finally 區塊確保清理動作執行,並在 finally 內再次 try-catch 避免清理時拋出例外掩蓋原始錯誤。
第 3-13 行。例外發生時無法得知正在處理哪筆資料、呼叫哪個方法。應在例外處理加入業務上下文(類別、方法、關鍵參數),並以易讀格式整理堆疊追蹤。
第 3-10 行。將大量程式碼塞入單一 try,難以定位具體拋出例外的陳述式與類型。應縮小 try 範圍,針對可能拋出例外的特定操作(如資料庫查詢、I/O 寫入)分別包裹。
第 6-8 行。迴圈中斷時,已輸出的資料不完整,下游系統收到錯誤資料卻無感知。解法:標記資料不完整(寫入警告標記)、或先緩衝全部資料再一次性輸出。
OutputStreamWriter out = ...;
java.sql.Connection conn = ...;
try {
Statement stat = conn.createStatement();
ResultSet rs = stat.executeQuery("select uid, name from user");
while (rs.next()) {
out.println("ID:" + rs.getString("uid") + ",姓名:" + rs.getString("name"));
}
} catch (SQLException sqlex) {
out.println("警告:資料不完整");
throw new ApplicationException("讀取資料時出現 SQL 錯誤", sqlex);
} catch (IOException ioex) {
throw new ApplicationException("寫入資料時出現 IO 錯誤", ioex);
} finally {
if (conn != null) {
try { conn.close(); }
catch (SQLException sqlex2) {
System.err.println(this.getClass().getName() + ".mymethod - 無法關閉資料庫連線: " + sqlex2);
}
}
if (out != null) {
try { out.close(); }
catch (IOException ioex2) {
System.err.println(this.getClass().getName() + ".mymethod - 無法關閉輸出檔案: " + ioex2);
}
}
}
這些反模式看似瑣碎,卻是生產環境故障的主要溫床。養成嚴謹的異常處理習慣,並在無把握時加上詳細註釋,是專業 Java 開發者的基本修養。