踏入 Java 世界的開發者,若能徹底搞懂以下三個基礎卻關鍵的問題,將為後續進階打下堅實基礎。即便自以為已超越初學者,若對這些概念仍感模糊,建議重新審視並夯實根基。
String s = "Hello world!";
許多人直覺回答「聲明了一個內容為 Hello world! 的 String 物件」,這種模糊認知正是誤區根源。精確來說:這行程式碼聲明了一個指向 String 物件的引用變數,名為 s,型別為 String,目前指向內容為 "Hello world!" 的 String 物件。並未建立新物件,僅建立一個能指向 String 物件的引用。
若接著執行 String string = s;,同樣只是新增一個名為 string 的引用,指向同一個物件,記憶體中並無第二個 String 物件產生。
== 與 equals() 的本質差異== 比較的是變數儲存的值。對基本型別(如 int)比較的是數值本身;對物件引用則比較記憶體位址。
String a = new String("foo");
String b = new String("foo");
a == b; // false,因為 new 在堆疊建立兩個不同位址的物件
equals() 則用於比較物件內容。Object 預設實現同 ==,子類別需覆寫以定義「相等」的業務邏輯。使用集合(HashSet、HashMap 等)時,務必確認該類別的 equals() 與 hashCode() 契約是否符合預期。
String 為不可變類別。執行 s = s + " world!" 時,原物件內容不變,s 改指向新建立的 "Hello world!" 物件,舊物件仍駐留記憶體(待 GC 回收)。頻繁修改字串易造成大量暫時物件,效能不彰,應改用 StringBuffer(或 StringBuilder)進行可變操作。
此外,字串常值池機制使相同字面值共享同一物件,故初始化時 s = "Initial Value" 優於 s = new String("Initial Value"),後者每次強制建立新物件,浪費資源。