Java通过ArrayList构造方法拷贝的列表为何独立,与按引用传递说法矛盾?
问题解答
你的操作和运行结果都没有问题,你和资料的表述差异来源于对「拷贝独立性」的定义混淆,new ArrayList<>(原列表)属于浅拷贝,具体特性如下:
1. 列表本身是完全独立的
new ArrayList<>(a)执行时会完成以下操作:
- 创建一个全新的
ArrayList实例,拥有独立的内部存储数组、元素计数等属性 - 把原列表
a内部数组中存储的元素引用,逐个复制到新列表的内部数组中
你执行的两类操作都是针对列表本身的结构,所以完全不会互相影响:
set(0, "B"):只是把copy列表内部数组第0位的引用,替换为指向新字符串"B"的地址,不会修改原列表a的数组存储remove操作:只是修改copy列表自身的元素计数、调整内部数组的元素排列,和原列表a完全无关
这也是你运行时看到两个列表输出完全独立的原因。
2. 元素层面存在引用依赖(仅针对可变元素)
资料提到的「按引用传递、存在依赖」,指的是浅拷贝没有复制元素对象本身,两个列表存储的是指向同一批对象的引用。
这种依赖只有在你修改可变元素的内部属性时才会体现,你当前用的是不可变的String类型,无法修改元素内部属性,所以感知不到。可以参考下面的示例验证:
// 自定义可变类 class User { String name; public User(String name) {this.name = name;} @Override public String toString() {return name;} } public static void main(String[] args) { ArrayList<User> a = new ArrayList<>(); a.add(new User("张三")); ArrayList<User> copy = new ArrayList<>(a); // 修改copy中元素的内部属性 copy.get(0).name = "李四"; // 两个列表的输出都会变成[李四] System.out.println(a); System.out.println(copy); }
总结
- 对列表本身做添加、删除、替换元素引用的操作,两个列表完全独立,互不影响
- 对列表存储的可变元素做内部属性修改时,修改会同时体现在两个列表中,这就是资料提到的依赖关系
内容的提问来源于stack exchange,提问作者anon
相关产品推荐
相关产品推荐

