iT邦幫忙

2026 iThome 鐵人賽

DAY 9
0
JavaScript

大學以前只看過那隻貓?用白話文帶你從 Python 跨進 JavaScript系列 第 9

【Day 9】心裡沒我就別想叫我!從互為配偶看懂 Java NullPointerException

  • 分享至 

  • xImage
  •  

今天我們要直面NullPointerException(簡稱 NPE,空指標例外)
用白話文來說:NPE 就是你手裡拿著一張根本沒寫地址的空白紙條,卻硬要外送員順著地址去送餐!

  1. 什麼是 null?連地皮都還沒買的空盒子
    當你宣告了一個物件變數,卻遲遲沒有執行 new 指令時:

Person p1; // 宣告了一個名為 p1 的容器,裡面預設裝著 null
你只是跟系統要了一個名為 p1 的容器,宣告「這個盒子未來專門用來放 Person 房子的地址」。
你還沒做什麼?
因為還沒寫 new Person()記憶體連一塊地都還沒開給你,更別說住人。
盒肚子裡裝了什麼?
既然沒房子,盒子裡空空如也,只能在裡面貼上一張白紙標記為 null(意思是:查無此處)。
2. 為什麼會噴出 NullPointerException?
就在容器裡還空空如也時,如果你迫不及待寫下這行:

p1.talk(); // 噴出 NullPointerException!
那個「點」是致命關鍵:在 Java 裡,點記號的動作叫做「順著地址走過去找物件」。
外送員打開 p1 容器,拿出一張寫著 null 的空白字條。順著紙條往前走,發現只有一望無際的空地。
外送員mermer:
「你叫我去執行 talk(),但我順著地址走過來連間空屋都沒看見!」

這就是空指標(Null Pointer)跳出來抗議(Exception)的真相
只要你試圖對著一個值為 null 的東西發出指令(按點號 .)系統就爆給你看!

  1. 戶政事務所的「單身悲劇」
    這種 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 教你做人!」

  1. 記憶體流浪兒:垃圾回收器(Garbage Collector, GC)
    搞懂了地址指向,我們來看看這段程式碼背後的記憶體變化:
    Person p1 = new Person("Kevin"); // 記憶體開了第 1 塊地,p1 指向 Kevin
    Person p2 = new Person("Chihua"); // 記憶體開了第 2 塊地,p2 指向 Chihua
    p1 = p2; // 讓 p1 也改指向 Chihua
    注意到了嗎?原本第 1 塊地裡的 Kevin,現在世界上沒有任何一支遙控器指向它了!無人認領的孤兒:在 Java 裡,只要一個物件失去它的地址),它就變成了系統裡的「記憶體垃圾」。Java 背景有一位稱職的清潔工叫做垃圾回收器(GC)。它會定期巡邏記憶體,把這些再也找不到的流浪兒清理乾淨、回收地皮,防止電腦記憶體被塞爆。

上一篇
【Day 8】老祖宗看不透你:用 @Override 覆寫 toString() 與 equals() 逆天改命!
下一篇
【Day 10】使用者不按牌理出牌?帶上 try-catch 防爆小組,程式絕不輕易死給你看
系列文
大學以前只看過那隻貓?用白話文帶你從 Python 跨進 JavaScript10
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言