首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計疑難解答

Java 集合 addAll 後修改元素對原集合的影響:引用類型共享 vs 值類型獨立

     編輯:程式設計疑難解答

核心結論

addAll 為淺拷貝:將源集合元素的引用複製到目標集合。修改影響取決於元素類型:

  • 引用類型(對象、數組):共享同一實例,修改內部字段/調用方法會相互影響。
  • 不可變類型(String、包裝類):修改實為替換引用,不影響原集合。
  • 值類型(基本類型自動裝箱):同不可變類型。

代碼驗證


// 1. 數組元素:共享引用
List list1 = new ArrayList<>();
String[] arr = {"a","b"};
list1.add(arr);
List list2 = new ArrayList<>();
list2.addAll(list1);
((String[])list2.get(0))[0] = "x";
System.out.println(((String[])list1.get(0))[0]); // "x" ← 相互影響

// 2. String 元素:替換不影響
List list3 = new ArrayList<>(Arrays.asList("a"));
List list4 = new ArrayList<>();
list4.addAll(list3);
list4.set(0, "b");
System.out.println(list3.get(0)); // "a" ← 不影響


深拷貝方案


// 手動深拷貝(簡單對象)
List deepCopy = src.stream()
    .map(o -> o.clone()) // 實現 Cloneable
    .collect(Collectors.toList());

// 通用序列化深拷貝
public static  List deepCopy(List src) {
    try (ByteArrayOutputStream bos = new ByteArrayOutputStream();
         ObjectOutputStream oos = new ObjectOutputStream(bos)) {
        oos.writeObject(src);
        try (ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
             ObjectInputStream ois = new ObjectInputStream(bis)) {
            return (List) ois.readObject();
        }
    }
}

建議

  • 明確業務是否需要共享狀態,默認使用 addAll(性能優)。
  • 需隔離時,構造函數傳入副本:new ArrayList<>(src) 仍是淺拷貝,需顯式深拷貝。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved