NullPointerException (NPE) 是 Java 開發中最常見的執行期錯誤。因 Java 到處都是物件,且每個參考都可能為 null,掌握防禦性程式設計技巧至關重要。
public boolean isNameEqual(String paraName) {
return paraName.equals(name); // 若 paraName 為 null → NPE
}
private String name = ""; // 預設空字串而非 null
public boolean isNameEqual(String paraName) {
return name.equals(paraName); // name 永不為 null,安全
}
當雙方都可能為 null 時:
public boolean isNameEqual(String paraName) {
if (name != null) {
return name.equals(paraName); // name 非 null,安全呼叫
} else if (paraName != null) {
return false; // name 為 null 而 paraName 非 null
} else {
return true; // 兩者皆為 null,視為相等(視業務邏輯而定)
}
}
Java 7+ 可用 Objects.equals(a, b) 簡化:
import java.util.Objects;
public boolean isNameEqual(String paraName) {
return Objects.equals(name, paraName); // 內建 null 安全比較
}
常見錯誤:宣告集合卻未初始化即使用
// 錯誤
public class Animator extends Applet implements Runnable {
Vector images; // 未初始化!
int imgNumber;
public void init() {
imgNumber = new Integer(getParameter("imgNumber")).intValue(); // 可能 NPE
for (int x = 0; x < imgNumber; x++) {
Image img = getImage(getDocumentBase(), "img" + (x+1) + ".jpg");
images.addElement(img); // NPE:images 為 null
}
}
}
public class Animator extends Applet implements Runnable {
Vector images = new Vector(); // 宣告即初始化
int imgNumber = 0; // 預設值
public void init() {
String param = getParameter("imgNumber");
if (param != null) {
try {
imgNumber = Integer.parseInt(param);
} catch (NumberFormatException e) {
imgNumber = 0; // 或記錄錯誤
}
}
for (int x = 0; x < imgNumber; x++) {
Image img = getImage(getDocumentBase(), "img" + (x+1) + ".jpg");
if (img != null) images.addElement(img); // 額外防護
}
}
}
Objects.requireNonNull(arg, "訊息") 在方法開頭快速失敗Collections.emptyList()、空字串 ""、或 Optional.empty()@NonNull、@Nullable (JSR-305 / SpotBugs / IntelliJ) 靜態分析JVM 參數 -XX:+ShowCodeDetailsInExceptionMessages (Java 14+) 可在 NPE 訊息中顯示具體是哪個變數為 null:
Exception in thread "main" java.lang.NullPointerException:
Cannot invoke "String.length()" because "name" is null
at com.example.Demo.main(Demo.java:10)
養成「先初始化、再使用、善用工具、早期驗證」的習慣,能將 NPE 風險降至最低。