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

Java 核心機制:引用、傳參、Clone 與淺/深拷貝完全解析

     編輯:Java 相關知識

Java 沒有指針,但有引用

Java 取消了 C/C++ 顯式指針,但 new 返回的本質是對象在堆中的地址——即引用。引用是訪問對象的唯一途徑。

傳參機制:值傳遞 vs 引用傳遞

原始類型:值傳遞

void changePrimitive(int x) { x = 20; }
int a = 10;
changePrimitive(a); // a 仍為 10

方法接收參數的副本,修改不影響原變量。

引用類型:引用的值傳遞(共享對象)

void changeObject(Point p) { p.x = 100; } // 修改對象內部狀態
Point pt = new Point(0,0);
changeObject(pt); // pt.x 變為 100

void reassign(Point p) { p = new Point(99,99); } // 修改引用本身
reassign(pt); // pt 仍指向原對象 (100,0),未變

核心結論:Java 只有值傳遞。傳遞對象時,傳遞的是引用的副本。副本指向同一對象,可修改對象內容;但無法在方法內讓原引用指向新對象。

賦值也是引用傳遞

Point a = new Point(1,1);
Point b = a; // b 指向同一對象
b.x = 5;
System.out.println(a.x); // 5

集合存儲的是引用

List list = new ArrayList<>();
StringBuilder sb = new StringBuilder("A");
list.add(sb);
sb.append("B");
list.add(sb);
// list 中兩個元素均指向同一 StringBuilder,內容均為 "AB"

Clone:對象拷貝的標準方式

為什麼需要 Clone?

賦值只能複製引用,無法創建獨立副本。clone() 創建新對象並複製字段值。

淺拷貝

  • 默認 Object.clone() 行為。
  • 原始類型字段:複製值。
  • 引用類型字段:複製引用,指向同一子對象。
class Shallow implements Cloneable {
    int[] arr;
    @Override protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}
Shallow s1 = new Shallow(); s1.arr = new int[]{1,2};
Shallow s2 = (Shallow) s1.clone();
s2.arr[0] = 99;
System.out.println(s1.arr[0]); // 99 —— 共享數組!

深拷貝

  • 遞歸拷貝所有引用類型字段指向的對象。
  • 實現方式:重寫 clone() 手動拷貝、序列化反序列化、構造函數拷貝、工具庫。
class Deep implements Cloneable {
    int[] arr;
    @Override protected Object clone() throws CloneNotSupportedException {
        Deep d = (Deep) super.clone();
        d.arr = arr.clone(); // 手動拷貝數組
        return d;
    }
}

深拷貝的幾種實現策略

方式優點缺點適用場景
重寫 clone() 手動拷貝性能高、可控代碼繁瑣、維護成本高、易漏字段簡單對象、性能敏感
序列化/反序列化通用、自動處理對象圖、支持循環引用需實現 Serializable、性能差、不支持 transient複雜對象圖、非高頻調用
JSON 序列化跨語言、可讀、庫成熟性能一般、不支持所有類型、需無參構造器DTO、配置對象、跨進程傳輸
構造函數/工廠方法拷貝清晰、類型安全、無反射需手動編寫、繼承體系麻煩不可變對象、值對象
第三方庫一行代碼、功能全引入依賴、反射/序列化有開銷通用場景、快速開發

最佳實踐建議

  1. 優先使用不可變對象:無需拷貝,天然線程安全。
  2. DTO/VO 用構造函數或 Builder 創建新實例,避免 clone 複雜度。
  3. 必須 clone 時:實現 Cloneable、重寫 clone() 為 public、處理深拷貝、文檔說明拷貝深度。
  4. 集合拷貝:new ArrayList<>(list)(淺)、Stream/map 收集(深)。
  5. 數組拷貝:Arrays.copyOf()、clone()、System.arraycopy()。

總結

Java 引用機制是「引用的值傳遞」,理解這一點能避免 90% 的參數傳遞誤解。Clone 是創建對象副本的標準手段,淺拷貝是默認行為,深拷貝需顯式實現。現代開發中,不可變設計 + 構造函數拷貝往往比 clone() 更優雅、更安全。

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