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

Java 對象引用與賦值機制深度解析:氣球與繩子模型

     編輯:Java 綜合教學

Java 對象引用與賦值機制深度解析:氣球與繩子模型

核心概念釐清

初學者最易混淆的點:**對象**與**對象引用**是兩個完全不同的實體。**引用不是對象**,它只是指向對象的「繩子」。

經典模型:氣球與繩子

  • 對象 = 堆內存中的大氣球(看不見摸不著,但真實存在)
  • 引用變量 = 手中的繩子(存儲在棧中,速度快)
  • new Vehicle() = 吹一個新氣球
  • Vehicle v = new Vehicle() = 吹氣球並用繩子 v 系住
  • v = null = 解開繩子,氣球飛走(成為垃圾回收候選者)
  • v2 = v = 另一根繩子 v2 也系住同一個氣球

代碼驗證:四種賦值場景

Vehicle v1 = new Vehicle();  // 繩子 v1 系住氣球 A
Vehicle v2 = v1;             // 繩子 v2 也系住氣球 A(複製的是繩子,非氣球)
v2 = new Vehicle();          // v2 改系氣球 B,氣球 A 仍被 v1 系住
v1 = v2;                     // v1 也改系氣球 B,氣球 A 無繩子系住 → 等待 GC 回收
new Vehicle();               // 臨時對象:吹氣球不系繩子,用完即丟(如 System.out.println("xxx"))

關鍵結論

  1. 一個引用指向 0 或 1 個對象
  2. 一個對象可被 N 個引用指向
  3. 對象無引用指向時,成為 GC 候選者(非立即回收)
  4. == 比較引用(繩子是否系同一氣球),equals() 比較內容(氣球長得像不像)

參數傳遞:Java 只有「值傳遞」

public class ParamTest {
    // 基本類型:傳值副本
    static void testBasic(int m) { m = 100; }
    
    // 引用類型不改變引用指向:影響原對象
    static void add(StringBuffer s) { s.append("_add"); }
    
    // 引用類型改變引用指向:不影響原對象
    static void changeRef(StringBuffer s) { s = new StringBuffer("Java"); }
    
    public static void main(String[] args) {
        int i = 50; testBasic(i);  // i 仍為 50
        
        StringBuffer sb = new StringBuffer("init");
        add(sb);       // sb 變為 "init_add"(同一氣球被修改)
        changeRef(sb); // sb 仍為 "init_add"(換了根繩子系新氣球,原氣球不變)
    }
}

本質:傳遞引用時,複製的是「繩子」(引用值/地址)。方法內修改對象內容 → 影響外部;方法內讓引用指向新對象 → 不影響外部。


面試必考:Test 對象傳遞變體

public class Test {
    public int i, j;
    
    // 情況 1:方法內 new 新對象並讓參數指向它
    public void test_m(Test a) { 
        Test b = new Test(); b.i=1; b.j=2; 
        a = b;  // 參數 a 換繩子系住 b,外部 t 不受影響
    }
    
    // 情況 2:直接修改參數指向的對象屬性
    public void test_m1(Test a) { a.i=1; a.j=2; } // 影響外部 t
    
    public static void main(String[] args) {
        Test t = new Test(); t.i=5; t.j=6;
        t.test_m(t);  // t 仍為 5,6
        t.test_m1(t); // t 變為 1,2
    }
}

記憶口訣

A a1 = new A(); → A 是類,a1 是引用,new A() 是對象
= 不是賦值,是傳地址:右邊對象地址傳給左邊引用
引用本質 = 指針(存地址),Java 表面無指針,實則皆指針

實戰陷阱:String 的特殊性


String s1 = "AAAA";
String s2 = s1;  // s2 系住同一氣球
s1 = "BBBB";     // s1 換繩子系新氣球 "BBBB",s2 仍系 "AAAA"
// String 不可變,任何「修改」實質都是新建對象

理解「引用傳遞的是地址值」,就能秒懂所有 Java 參數傳遞、賦值、GC 行為。

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