異常堆疊
Exception in thread "main" java.lang.NullPointerException
at PassengerFlight.postpone(PassengerFlight.java:50)
at PassengerFlight.main(PassengerFlight.java:68)
問題代碼定位
// PassengerFlight.java:50
for (int i = 0; i <= this.getNumSold(); i++) { // 錯誤:<=
System.out.println("Notify passenger " + passengers[i].getName() + ...);
}
根本原因
passengers 數組長度 = seat (構造函數 new Person[seat])。
numSold 記錄已售票數(有效乘客數),最大值 = seat。
- 循環條件
i <= numSold 導致最後一次迭代 i == numSold,訪問 passengers[numSold] —— 該下標**超出有效範圍**(有效 0 ~ numSold-1),且該位置從未賦值,為 null。
- 調用
passengers[i].getName() 觸發 NullPointerException。
修正代碼
// 修正:< 而非 <=
for (int i = 0; i < this.getNumSold(); i++) {
System.out.println("Notify passenger " + passengers[i].getName() + " at " + passengers[i].getEmail() + ".");
}
通用排查口訣
- 看行號:堆疊指向具體行(此處第 50 行)。
- 找對象:該行調用方法/訪問字段的對象是誰(
passengers[i])。
- 問來源:對象從哪來?(數組元素)。
- 查賦值:所有訪問路徑是否已賦值非 null?(
sellTicket 僅賦值 0~numSold-1)。
- 核邊界:循環/下標是否超出已賦值範圍?(
<= 導致多訪問一個 null)。
最佳實踐:防御性編程
// 1. 循環用 < 而非 <=
for (int i = 0; i < passengers.length && i < numSold; i++) { ... }
// 2. 或使用增強 for(自動避免下標錯誤)
for (Person p : passengers) {
if (p != null) System.out.println("Notify " + p.getName() + "...");
}
// 3. 數組改用 List,尺寸動態匹配實際元素
private List passengers = new ArrayList<>();
// sellTicket 內:passengers.add(buyer);
// postpone 內:passengers.forEach(p -> notify(p));