java - java在处理ArrayLists时如何处理对象引用?
问题描述
在编写一段代码时,我观察到一个不寻常的行为。有一个类对象,它具有另一个名为 as的obj1
类对象的数组列表。请参阅代码以供参考:obj2
list1
PriorityQueue<Obj2> pq = new PriorityQueue<>(Comparator);
pq.addAll(new ArrayList<>(obj1.getList()));
Obj2 obj2 = pq.poll();
obj2.setField("any value");
System.out.println(obj2);
System.out.println(obj1.getList().get(0));
上面的两个 sout 语句都打印了该值。
为什么会这样?我在 pq 中更改了 obj2 引用的值,而不是在 Obj1 本身中
在向 中添加元素时pq
,如果我们不使用,new ArrayList<>()
那么如果两个引用都指向同一个对象是可以理解的,但是我创建了一个新的 ArrayList 来添加pq
,仍然发生这种情况。
解决方案
JavaDocArrayList(Collection<? extends E> c)
说:_
按照集合的迭代器返回的顺序构造一个包含指定集合元素的列表。
它没有说“复制”。
Java 中也没有“深拷贝”机制。即使您使用Object.clone
(通常不应该这样做),您也只会复制此对象内的引用。引用本身仍将指向原始内容。
例如:
class Obj {
String a;
int b;
OtherObj c;
}
在内存中,这将如下所示:
[Reference To String a] [Value of int b] [Reference to OtherObj c]
(只有原始类型将直接存储在对象中,其他所有内容都是 aClass
并将作为引用存储。即使是像这样的原始包装器Integer
也是类并将作为引用存储,但是这些原始包装器是不可变的,尽管你不能改变他们的内在价值)
虽然如果您创建此对象的副本,您将获得副本的新内存位置,但该内存位置将包含相同的数据:[Reference To String a] [Value of int b] [Reference to OtherObj c]
.
同样的情况也发生在ArrayList
. 在内存中它看起来像这样:
[Reference to Element 1] [Reference to Element 2] [Reference to Element 3] ...
如果您复制该列表,您将在内存中获得该部分的副本。但是所有的引用仍然指向同一个对象。
这一切都可能随着 Project Valhalla 和 Value 类型的引入而改变。但这可能仍需要数月或数年。
推荐阅读
- postgresql - How to get proper Json response from a postgresql in spring boot?
- bootstrap-4 - Bootstrap: unequal columns on stacked
- android - A conext menu is shown in a small area instead of full screen on Android Pie
- javascript - Meteor方法404错误但登录控制台
- python - Transfering cookies from a Request session to a selenium session
- vue.js - why my code not working on ie11 after i use babel-polyfill?
- python - OpenCV image stitching never finishes
- android - Implementing Custom Back Navigation in Android
- android - Is there a way to store registered devices FCM tokens in Firebase Console?
- linq - How to calculate the 5th heighest salary from Employee Table and Salary Table using LINQ query