public String getAnswer() {
String myAnswer; // 僅宣告,未初始化
try {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
myAnswer = br.readLine().toString(); // 嘗試賦值
System.out.println("你輸入的是:" + myAnswer);
} catch (Exception e) {
// 吞沒例外,myAnswer 可能仍未賦值
}
return myAnswer; // 編譯錯誤:variable myAnswer might not have been initialized
}
Java 編譯器進行 **確定性賦值分析 (Definite Assignment Analysis)**:區域變數在**所有可能執行路徑**上必須被明確賦值後才能讀取。上述程式碼中,若 br.readLine() 拋出例外 (如串流關閉)、或 catch 區塊捕獲例外後未賦值,return myAnswer 將讀取未初始化變數,編譯器直接報錯。
public String getAnswer() {
String myAnswer = ""; // 給予預設值
try {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
myAnswer = br.readLine(); // readLine() 已回傳 String,無需 toString()
System.out.println("你輸入的是:" + myAnswer);
} catch (Exception e) {
// 記錄日誌或處理,myAnswer 保持預設值 ""
}
return myAnswer; // 安全:所有路徑皆有值
}
public class AnswerHandler {
private String myAnswer; // 欄位自動初始化為 null
public String getAnswer() {
try {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
myAnswer = br.readLine();
System.out.println("你輸入的是:" + myAnswer);
} catch (Exception e) {
// myAnswer 保持 null
}
return myAnswer;
}
}
注意:欄位預設值為 null/0/false,若呼叫端未檢查 null 可能拋出 NPE,語意上不如模式一明確。
public String getAnswer() {
String myAnswer;
try {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
myAnswer = br.readLine();
System.out.println("你輸入的是:" + myAnswer);
} catch (Exception e) {
myAnswer = "DEFAULT"; // 例外路徑明確賦值
}
return myAnswer; // 編譯器確認所有路徑皆有賦值
}
public String getAnswer() {
try (var br = new BufferedReader(new InputStreamReader(System.in))) {
return br.readLine(); // try-with-resources 自動關閉,單一返回點
} catch (Exception e) {
return "DEFAULT";
}
}
catch 區塊被視為一條獨立執行路徑。try-with-resources 簡化資源管理。| 誤區 | 正確認知 |
|---|---|
| 「try 裡賦值了,catch 不會執行吧」 | 編譯器假設 catch 可能執行,除非方法標註 @SuppressWarnings("unchecked") 等 (不影響 DA 分析) |
| 「欄位也要初始化」 | 欄位有預設值 (null/0/false),區域變數無 |
| 「加上 throws Exception 就不用 catch」 | 若拋出受檢例外,呼叫端仍需處理;區域變數初始化問題依然存在 |