一不小心就是一个bug ,其实是很基础的问题,有时写代码为了好看点,习惯性的就把集合的创建和引用类型的元素添加写在一块。
public static void main(String[] args) {
List<Map<String,Object>> source = new ArrayList<Map<String,Object>>();
List<Map<String,Object>> target = new ArrayList<Map<String,Object>>();
// 错误使用:addAll在target添加元素前执行
source.addAll(target);
Map map = new HashMap();
map.put("a",3);
target.add(map);
System.out.println("addAll在target添加元素前执行的source:"+source);
// 正确使用:addAll在target添加元素后执行的
source.addAll(target);
System.out.println("addAll在target添加元素后执行的source:"+source);
// addAll 底层是浅拷贝
map.put("b",4);
System.out.println("addAll是浅拷贝:"+source);
}
运行结果:
addAll在target添加元素前执行的source:[]
addAll在target添加元素后执行的source:[{a=3}]
addAll是浅拷贝:[{a=3, b=4}]
源码分析:
public boolean addAll(Collection<? extends E> c) {
Object[] a = c.toArray();
int numNew = a.length;
ensureCapacityInternal(size + numNew); // Increments modCount
System.arraycopy(a, 0, elementData, size, numNew);
size += numNew;
return numNew != 0;
}
很显然,addAll是先将集合c转换成数组a,然后通过System.arraycopy对两个数组进行合并;addAll写在最前面,此时c是空的,所以显然source也是空的。另外,addAll底层也是浅拷贝。