完成了第二週的演算法與資料結構解題後,從今天開始,我們正式邁入工程師日常開發中最耗時、也最考驗功力的環節——「系統維護、代碼重構與除錯(Debug)」。
在實際專案中,我們每天要面對的往往不是乾淨的演算法題目,而是終端機裡動輒幾十行的紅色報錯訊息(Error Stack Trace)。特別是在多層架構(Controller -> Service -> Repository)的 Spring Boot 或 Java 應用中,初學者常常盯著一整頁的堆疊追蹤不知所措,只能盲目下斷點或加 System.out.println。
今天我們就來示範:如何將 ChatGPT 當作資深除錯顧問,藉由結構化 Prompt 快速解讀 Stack Trace,精準抓出空指標(NullPointerException)與語意邏輯錯誤!
貼報錯給 AI 時,千萬不要只丟一句「這段為甚麼錯了?」。提供足夠的上下文能讓 AI 在 3 秒內定位問題:
【除錯分析提示詞範本】
請扮演資深 Java 後端架構師與除錯專家。我的系統在運行時發生了例外,以下是相關資訊:
請依序提供以下診斷:
假設我們有一個電商會員服務,負責計算會員的折扣價:
[涉及問題的業務代碼]
public class DiscountService {
public double calculateDiscountedPrice(Order order) {
// 取得會員等級折數
double discountRate = order.getUser().getMembership().getDiscountRate();
return order.getTotalAmount() * discountRate;
}
}
[執行時噴出的錯誤堆疊]
Exception in thread "main" java.lang.NullPointerException: Cannot invoke "Membership.getDiscountRate()" because the return value of "User.getMembership()" is null
at com.example.service.DiscountService.calculateDiscountedPrice(DiscountService.java:5)
at com.example.app.OrderController.checkout(OrderController.java:24)
at com.example.app.Application.main(Application.java:12)
將上述訊息送入提示詞模板後,AI 會直接切中要害:
order 或 order.getUser(),而是使用者的會員物件 getMembership() 回傳了 null。a.getB().getC().getD())是典型的火車代碼(Train Wreck Code),極易違反迪米特法則(Law of Demeter),只要中間任何一個節點為空就會崩潰。AI 提供的現代 Java 防禦性修復方案:
[優化後的防禦代碼]
import java.util.Optional;
public class DiscountService {
private static final double DEFAULT_DISCOUNT_RATE = 1.0; // 無會員預設不打折
public double calculateDiscountedPrice(Order order) {
if (order == null) {
throw new IllegalArgumentException("訂單物件不可為 null");
}
// 利用 Optional 優雅處理可能為空的多層物件
double discountRate = Optional.ofNullable(order.getUser())
.map(User::getMembership)
.map(Membership::getDiscountRate)
.orElse(DEFAULT_DISCOUNT_RATE);
return order.getTotalAmount() * discountRate;
}
}
透過 AI 輔助 Debug,我們可以建立起一套標準的排查肌肉記憶:
Caused by:,並過濾出自己專案 Package(如 com.example)的第一行,那裡就是事發現場。.get().get(),都應該透過 Optional 或提早 Return(Guard Clauses)進行防呆。今天我們示範了如何透過結構化的 Debug Prompt,讓 AI 快速穿透冗長的 Stack Trace 定位到空指標的核心根因,並利用 Optional 寫出健壯的防禦性程式碼。