今天我們要直面NullPointerException(簡稱 NPE,空指標例外)
用白話文來說:NPE 就是你手裡拿著一張根本沒寫地址的空白紙條,卻硬要外送員順著地址去送餐!
Person p1; // 宣告了一個名為 p1 的容器,裡面預設裝著 null
你只是跟系統要了一個名為 p1 的容器,宣告「這個盒子未來專門用來放 Person 房子的地址」。
你還沒做什麼?
因為還沒寫 new Person()記憶體連一塊地都還沒開給你,更別說住人。
盒肚子裡裝了什麼?
既然沒房子,盒子裡空空如也,只能在裡面貼上一張白紙標記為 null(意思是:查無此處)。
2. 為什麼會噴出 NullPointerException?
就在容器裡還空空如也時,如果你迫不及待寫下這行:
p1.talk(); // 噴出 NullPointerException!
那個「點」是致命關鍵:在 Java 裡,點記號的動作叫做「順著地址走過去找物件」。
外送員打開 p1 容器,拿出一張寫著 null 的空白字條。順著紙條往前走,發現只有一望無際的空地。
外送員mermer:
「你叫我去執行 talk(),但我順著地址走過來連間空屋都沒看見!」
這就是空指標(Null Pointer)跳出來抗議(Exception)的真相
只要你試圖對著一個值為 null 的東西發出指令(按點號 .)系統就爆給你看!
戶政事務所的「單身悲劇」
這種 Bug 最常發生在「兩個物件互相關聯」的情境。想像你在寫戶政系統的「登記配偶」功能:
public class Person {
private String name;
private Person spouse; // 心裡的位置:配偶欄(預設是 null,一片空白)
public Person(String name) {
this.name = name;
}
public void setSpouse(Person spouse) {
this.spouse = spouse;
}
public void talk() {
// 伸手摸摸心裡的位置,順著地址去找另一半的名字
System.out.println("我的配偶是:" + this.spouse.getName());
}
}
如果在主程式裡這樣寫:
Person p1 = new Person("Kevin");
p1.talk(); //螢幕噴出滿滿的 NPE
為什麼會當場炸裂?
Kevin 剛 new 出來時還是個母胎單身漢,他心裡的配偶欄位空空如也,裝著大大的 null。
你偏偏在這時叫他 talk(),程式執行到 this.spouse.getName(),等於逼一個黃金單身漢伸手對著空氣掏出另一半,電腦原地崩潰,賞你一個 NullPointerException!
婚姻真理:心裡要有對方!兩邊都要在自己身上騰出空間裝彼此
很多人以為現實中去喝了喜酒,電腦就會通靈知道「你們結婚了」。
但在冷血的 Java 世界裡,婚姻是平等的,愛必須是雙向奔赴!既然結婚,你們兩個人的身上都必須為對方保留一個空間,並且親手把對方的地址放進自己心坎裡:
Person p1 = new Person("Kevin");
Person p2 = new Person("Alice");
//雙向奔赴:兩個人都要在自己心裡騰出空間,把對方的地址刻上去!
p1.setSpouse(p2); // Kevin 心裡有 Alice
p2.setSpouse(p1); // Alice 心裡也裝著 Kevin
p1.talk(); //印出:「我的配偶是:Alice」!
如果只有單向:
只寫 p1.setSpouse(p2);,代表只有 Kevin 一廂情願把 Alice 放在心上,Alice 的心裡依然是 null(依然查無此人)。等哪天呼叫 p2.talk(),換 Alice 要找配偶時,系統當場被這段「單戀」給炸得粉身碎骨!
一句話總結:
「談戀愛可以搞曖昧,寫 Java 必須雙向登記!只要你心裡裝著 null 卻硬要開口叫對方,Java 就用 NPE 教你做人!」