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

Java 參考傳遞深度解析:引用與對象實例的區別

     編輯:Java 綜合教學

核心結論

Java 只有值傳遞。傳遞物件時,傳的是引用的副本(指向同一堆內存對象)。引用變量可指向子類實例,但編譯期類型決定可訪問成員。

代碼演示

package test;

public class FatherClass { protected int i = 0; }

public class Child extends FatherClass {
    public int i1 = 1;
    public void function() { System.out.println("call Child function"); }

    public static void main(String[] args) throws Exception {
        // 1. 父類引用指向子類實例
        FatherClass f = new Child();
        // f.function(); // 編譯錯誤:FatherClass 無此方法
        System.out.println(f.getClass()); // class test.Child

        // 2. 向下轉型:子類引用指向同一實例
        Child c1 = (Child) f;
        c1.function(); // 正常調用
        System.out.println(c1.getClass()); // class test.Child

        // 3. 反射繞過編譯期檢查
        Method m = Child.class.getMethod("function");
        m.invoke(f); // 正常輸出(運行時類型為 Child)

        // 4. 危險:子類引用指向父類實例
        Child c2 = (Child) new FatherClass(); // 編譯通過,運行拋 ClassCastException
        m.invoke(c2); // 異常
    }
}

執行輸出

the entrance.
----------------
test.Child@2a139a55
class test.Child
----------------
call Child function
test.Child@2a139a55
class test.Child
call Child function
Exception in thread "main" java.lang.ClassCastException: test.FatherClass cannot be cast to test.Child

關鍵知識點

  1. 引用類型 vs 實例類型:FatherClass f = new Child(),引用類型是 FatherClass,實例類型是 Child。
  2. 編譯期綁定:只能調用引用類型聲明的成員(f.function() 編譯失敗)。
  3. 運行期多態:實例方法調用看實際類型(反射 invoke 亦同)。
  4. 向下轉型風險:(Child) new FatherClass() 編譯不報錯,運行必崩——父類實例不是子類。
  5. instanceOf 守衛:轉型前務必 if (obj instanceof Child)。

記憶體圖解

棧 (Stack)                    堆
f  ──────────────────────►  Child 實例 (含 i=0, i1=1)
c1 ──────────────────────►  同一 Child 實例
c2 ──────────────────────►  FatherClass 實例 (僅 i=0)  ← 類型不匹配,轉型失敗

搞清「引用」與「實例」的關係,是避免 ClassCastException、正確使用多態的關鍵。

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