首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 綜合教學

Java String 不可變性與參數傳遞機制:賦值陷阱深度解析

     編輯:Java 綜合教學

核心結論

String 不可變:一旦創建,內容不可更改。所有「修改」操作實際返回新對象。
Java 傳值調用:基本類型傳值,引用類型傳引用的值(即地址副本)。方法內修改引用指向不影響外部原引用。

案例一:引用重新賦值

public class Example {
    String str = new String("good");
    char[] ch = { 'a', 'b', 'c' };

    public static void main(String[] args) {
        Example ex = new Example();
        ex.change(ex.str, ex.ch);
        System.out.println(ex.str); // good
        System.out.println(ex.ch);  // gbc
    }

    public void change(String str, char[] ch) {
        str = "test ok";      // 參數 str 指向新對象,外部 ex.str 不變
        ch[0] = 'g';          // 參數 ch 指向同一數組,修改內容影響外部
    }
}

內存圖解

  • 調用前:ex.str → "good" (0x100);ex.ch → ['a','b','c'] (0x200)
  • 進入方法:str (參數) → 0x100;ch (參數) → 0x200
  • str = "test ok":參數 str → "test ok" (0x300),ex.str 仍指向 0x100
  • ch[0] = 'g':修改 0x200 處數組內容為 ['g','b','c'],外部可見

案例二:調用不可變方法 & 參數重新賦值

public void change(String str, char[] ch) {
    str = str.toUpperCase();  // 返回新字符串 "GOOD",參數 str 指向新對象
    ch = new char[]{ 'm', 'n' }; // 參數 ch 指向新數組,外部 ex.ch 不變
}
// 結果:ex.str="good", ex.ch=['a','b','c']

關鍵點

  • toUpperCase() 不修改原對象,返回新對象
  • ch = new ... 只改變參數局部引用,斷開與外部數組的關聯

底層原理

String 實現

public final class String {
    private final char value[]; // final 數組引用
    private int hash; // 緩存 hashCode
    // 所有構造器最終複製字符數組
    // 所有「修改」方法返回 new String(newValue)
}

字符串常量池

  • String s = "abc":編譯期確定,進常量池,相同字面量共享對象
  • String s = new String("abc"):運行期在堆創建新對象,不進常量池(除非調用 intern())
  • String.intern():若常量池已有相同內容返回池中引用,否則放入池並返回

最佳實踐

  1. 拼接用 StringBuilder:循環拼接避免產生大量中間 String 對象
  2. 比較用 equals():== 比較引用,equals() 比較內容
  3. 參數傳遞認知:方法無法修改調用者的引用指向,只能修改引用指向的對象內容(若對象可變)
  4. 防禦性複製:可變對象作為參數/返回值時,考慮複製副本防止外部竄改

延伸閱讀

三分鐘理解 Java 中字符串(String)的存儲和賦值原理

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved