此系列問題為每位 Java 學習者必修課。若自以為超越初階卻不甚理解,請重回基礎夯實。
String s = "Hello world!";
許多回答:「一個內容為 Hello world! 的 String」。這模糊認知是概念不清根源。精確回答:聲明一個指向物件的引用變數,名為 s,型別為 String,目前指向內容為 "Hello world!" 的 String 物件。並未建立物件,僅建立引用。
若接著執行:
String string = s;
同樣只是聲明另一個 String 型別引用 string,指向同一個物件,記憶體中並無第二個物件產生。
== 比較變數值是否相等(即記憶體位址)。
int a = 10, b = 10; // a == b → true (基本型別比值)
String a = new String("foo");
String b = new String("foo"); // a == b → false (兩個不同物件,位址不同)
物件變數值為記憶體位址,new 產生兩個獨立物件,位址不同故 == 為 false。內容比較才是 equals() 的職責。
boolean equals(Object o) { return this == o; }
預設同 ==。若自訂類別未覆寫 equals(),結果同 ==。equals() 語義由類別設計者定義,極端例子:
class Monster {
boolean equals(Object another) { return true; } // 任何實例永遠相等
}
使用 equals() 或散列集合 (HashSet/HashMap/Hashtable) 時,必須查閱該類別文檔確認 equals 邏輯,切勿想當然。
String s = "Hello";
s = s + " world!";
String 物件從未改變。String 為 immutable(不可變)類別。執行 + 運算時,s 改指向新建立的 "Hello world!" 物件,原 "Hello" 物件仍在記憶體中,只是無引用指向。
頻繁修改字串若用 String 會產生大量臨時物件,造成記憶體壓力。此時應改用 StringBuffer(或 StringBuilder),允許就地修改,兩者轉換容易。