Exception 非 RuntimeException,編譯器強制 try-catch 或 throws(如 IOException)RuntimeException 及其子類、Error,編譯器不強制,通常表示編程錯誤或系統級故障// 惡劣 1:捕獲後什麼都不做
try { risky(); } catch (Exception e) { /* 空 */ }
// 惡劣 2:捕獲 Exception 甚至 Throwable
try { ... } catch (Throwable t) { log(t); } // 掩蓋 Error,導致 JVM 關鍵故障被忽略
// 惡劣 3:異常作控制流
try { int i = map.get(key); } catch (NullPointerException e) { i = defaultValue; } // 應用 map.containsKey()
後果:Bug 隱匿、根因丟失、性能損耗、維護噩夢。
// 不好 1:只打印堆棧,繼續執行導致後續 NPE
try { InputStream in = new FileInputStream(f); } catch (FileNotFoundException e) { e.printStackTrace(); }
in.read(); // 此處 in 為 null → NPE
// 不好 2:包裝異常丟失原始堆棧
try { ... } catch (SQLException e) { throw new RuntimeException(e.getMessage()); } // 無 cause
// 不好 3:過度寬泛 throws
public void doAll() throws IOException, SQLException, TimeoutException, ParseException { ... } // 調用者無法針對性處理
// 優 1:精準捕獲,業務語義包裝,保留因果鏈
try {
return parseConfig(file);
} catch (IOException e) {
throw new ConfigLoadException("無法讀取配置:" + file, e); // 自定義異常攜帶原因
} catch (ParseException e) {
throw new ConfigLoadException("配置格式錯誤:" + file, e);
}
// 優 2:try-with-resources 確保資源釋放,異常自動抑制
public String readFirstLine(Path path) throws IOException {
try (BufferedReader br = Files.newBufferedReader(path, StandardCharsets.UTF_8)) {
return br.readLine();
}
}
// 優 3:異常轉換邊界清晰:持久層 → 服務層 → 控制層
@Repository
public class UserDao {
public User findById(Long id) {
try { return jdbc.queryForObject(sql, mapper, id); }
catch (EmptyResultDataAccessException e) { return null; } // 正常業務:不存在
catch (DataAccessException e) { throw new PersistenceException("DB錯誤", e); } // 異常:包裝上拋
}
}
@Service
public class UserService {
public UserDTO getUser(Long id) {
User u = dao.findById(id);
if (u == null) throw new UserNotFoundException(id); // 業務異常
return mapper.toDTO(u);
}
}
@RestControllerAdvice
public class GlobalHandler {
@ExceptionHandler(UserNotFoundException.class)
public ResponseEntity handle(UserNotFoundException e) {
return ResponseEntity.status(404).body(new ErrorResp("USER_NOT_FOUND", e.getMessage()));
}
@ExceptionHandler(PersistenceException.class)
public ResponseEntity handle(PersistenceException e) {
log.error("持久層故障", e); // 記錄完整堆棧
return ResponseEntity.status(500).body(new ErrorResp("SYSTEM_ERROR", "服務暫時不可用"));
}
}
RuntimeException(業務異常)或 Exception(可恢復受檢異常)message、message + cause、causeuserId, orderNo, errorCodeException 結尾,語義清晰:InsufficientBalanceExceptionWARN 級別記錄關鍵信息(不打印全棧)ERROR 級別記錄完整堆棧 + 關鍵參數