Java中的“浅拷贝与深拷贝”
今天在使用Arrays的时候,偶然发现了一个与前面Python的一篇文章类似的问题,也就是浅拷贝与深拷贝的问题,链接如下:
http://www.cnblogs.com/sumory/archive/2011/01/18/1938551.html
List<String> list3 = Arrays.asList(strs);
Collections.shuffle(list3);//random
print(list3);
for (String u : strs)
{
System.out.println(u);
}
System.out.println(list3.get(0).hashCode()+" "+strs[0].hashCode()); //结果相同
上面的结果是list3顺序改变,数组顺序同list3一样,也发生改变。我们猜想,Arrays.asList只不过把list3指向了数组,并没有产生新数据,list3所做的更改会反映到strs上。实验验证以上想法:
List<String> list3 = Arrays.asList(strs);
print(list3);
Collections.shuffle(list3);
print(list3);
for (String u : strs)
{
System.out.println(u);
}
System.out.println(list3.get(0).hashCode()+" "+strs[0].hashCode());//the same
list3.set(0,"i am changed");
print(list3);
for (String u : strs)
{
System.out.println(u);
}
打印显示,跟我们想的一样,strs和list3的第一个元素都变为了"i am changed"。
综合上述,可以看出, Arrays.asList 使用的是浅拷贝,同时list3已经不能在调用add方法了(请看jdk源码注释),这样请尤其注意不要随便使用这个方法,因为新list的操作会反映到原数据上。
我们再来看一下"深拷贝"的情况:
将List<String> list3 = Arrays.asList(strs);换为List<String> list2 = new ArrayList<String>(Arrays.asList(strs)); ,会发现结果就完全不同了,list3的操作不再会作用到strs上,同时list3也可使用一般ArrayList跟size相关的操作了,这是因为new了新对象,具体就不介绍了,大家应该一看就懂。
ps:其实,这种api如果不看源码的话(尤其是注释),很容易因为稀里糊涂地采用而导致出错。大家还有什么这种类似的问题请发上来讨论,共同进步!