java ArrayList返回类型方法是返回ArrayList变量的内存地址还是它的副本?
我有一段代码:
public class Check {
private ArrayList<Integer> diameters; // Array of diameters
public Check(int num) {
diameters = new ArrayList<>(num); // Create an ArrayList object.
for(int i = 0; i < num; i++) { // Initialize the ArrayList.
diameters.add(i, i + 1);
}
}
public ArrayList<Integer> getDiameters() {
return new ArrayList<Integer>(diameters);
}
}
getDiameters()
方法是否返回diametersArrayList
的内存地址(如果是,我是否需要像在构造函数中那样单独复制每个值),还是返回diametersArrayList
中所有整数的副本
getDiameters()
方法的返回值和变量diameters
是否指向同一个内存位置
在getDiameters()
方法中,下面的返回语句是否是一个有效的语句,不会对安全性造成任何损害,而不是写“return new ArrayList<Integer>(diameters);
”
return diameters;
如果我写上述声明,面临哪些安全问题(如果有的话)
# 1 楼答案
对于对象,Java将引用传递给对象,因此该方法不会返回列表的深度副本
至于安全问题,这意味着如果用户操作
return diameters
返回的对象,这些更改也会影响Check
对象引用的对象,因为它们是同一个对象,这可能是一个问题# 2 楼答案
如果你做了
return diameters;
,你的整个diameters
数组列表将是可变的,因为你提供了一个直接指向它的链接。这意味着你可以从外部影响它的大小和内容执行
new ArrayList<Integer>(diameters)
操作时,您提供的是一个带有复制值的ArrayList副本(这些值是通过引用复制的,因此基本上与原始集合中的对象相同)对于像Integer这样的原始包装器,它是安全的,但如果在集合中传递可变对象,它的更改将更改原始ArrayList内容
简单的例子:
一般来说,为了保护所有需要传递的不可变集合和不可变对象。 首先可以通过使用
com.google.common.collect.ImmutableList.of
来实现# 3 楼答案
getDiameters()将返回新创建的ArrayList的地址内存。它们不指向同一个地址内存。它会将直径元素复制到新的ArrayList。如果有多个线程,请使用Arraylist,出于安全考虑,您可以使用:
Collections.synchronizedList(list);
# 4 楼答案
创建Integer的新ArrayList,让我们引用文档中的内容:
https://docs.oracle.com/javase/8/docs/api/java/util/ArrayList.html#ArrayList-java.util.Collection-
现在,您已经将一个
Collection
传递给了构造函数,该构造函数会生成一个ArrayList,它与您的数据成员类似,但不相同。如果您没有很好的理由这样做,则不建议这样做,因为直径已经包含您拥有的元素至于安全性,我所看到的唯一安全性问题是,使用diameters的代码将拥有对实际
ArrayList
的写操作权限。如果您打算阻止这种情况,那么不要返回实际的ArrayList
。你可以clone
它或者创建另一个ArrayList
(就像你做的那样),或者你可以(在我看来这是最优雅的解决方案)调用unmodifiableList来返回你的Collection
的只读版本