gpt4 book ai didi

java - 有人可以解释深拷贝和防御拷贝之间的区别吗?

转载 作者:塔克拉玛干 更新时间:2023-11-02 08:39:01 26 4
gpt4 key购买 nike

我的教授说它们完全不同,但我读到它们非常相似。我不知道他指的是什么上下文“不同”。如果这个问题已经得到回答,只需链接它。谢谢。

最佳答案

深拷贝:对象拷贝技术的一种:将结构体中的所有数据进行深度拷贝。生成对象深拷贝的“苛刻”方法是先序列化然后反序列化。对于树,一般来说,递归复制是一种有效的解决方案。

防御性副本:保护内部数据的操作结果。通常它是一个深拷贝或浅拷贝,用于防止通过内部引用结果进行不希望的访问。例如:

public int[] getValues() {
return Arrays.copyOf(values, values.length);
}

通常,您应该使用防御性副本来保护内部数组、集合或其他结构。如果我们简单地返回(引用)数组,用户就可以修改我们的内部结构!

让我们看一个例子。

Tom 编写了一个延迟缓存 Integer 集合的一些聚合的类:

public class CachedIntegerAggregator {

private List<Integer> integers;

private boolean isSumCalculated = false;
private int sum = 0;

private boolean isMultiCalculated = false;
private int multi = 0;

public CachedIntegerAggregator(Integer... integers) {
this(Arrays.asList(integers));
}

public CachedIntegerAggregator(Collection<Integer> integers) {
this.integers = new ArrayList<Integer>(integers);
}

public List<Integer> getIntegers() {
return integers;
}

public int getSum() {
if (!isSumCalculated) {
sum = 0;
for (Integer integer: integers) {
sum += integer;
}
isSumCalculated = true;
}
return sum;
}

public int getMulti() {
if (!isMultiCalculated) {
multi = 1;
for (Integer integer: integers) {
multi *= integer;
}
isMultiCalculated = true;
}
return multi;
}

}

Jerry 是这样使用上面的类的:

CachedIntegerAggregator aggregator = new CachedIntegerAggregator(2, 3, 4);

// hm, what is the sum?
System.out.println(aggregator.getSum());

// let's print of integers
List<Integer> integers = aggregator.getIntegers();
System.out.println(integers);

// now, see the double
int size = integers.size();
for (int i = 0; i < size; i++) { // (oops! this changes internal data!)
integers.set(i, integers.get(i) * 2);
}
System.out.println(integers);

// hm, see sum and multi
System.out.println(aggregator.getSum());
System.out.println(aggregator.getMulti()); // (oops! total inconsistency!)

输出:

9
[2, 3, 4]
[4, 6, 8]
9
192

主要问题是什么?汤姆泄露了一个可变的内部结构。解决办法是什么?在 getIntegers() 中,在返回之前复制它:

public List<Integer> getIntegers() {
return new ArrayList<Integer>(integers);
}

在某些情况下,不可变包装器也是正确的:

public List<Integer> getIntegers() {
return Collections.unmodifiableList(integers);
}

性能?一般来说,不用担心。快速创建对象是 Java 的主要优势之一。当然,也有复杂的结构,复制起来效率低下。在这种情况下,您可以使用写时复制技术。一些大数据结构实现内置了写时复制支持,例如 BigList .

关于java - 有人可以解释深拷贝和防御拷贝之间的区别吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36586412/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com