我的教授说它们完全不同,但我读到它们非常相似。我不知道他指的是什么不同的语境。如果这个问题已经被回答了,就把它链接起来。谢谢。
深度复制:一种对象复制技术:深度复制结构中的所有数据。A";苛刻的";生成对象的深层副本的方法是先序列化,然后反序列化。对于树,递归复制通常是一种有效的解决方案。
防御性拷贝:保护内部数据的操作结果。通常,它是一个深度或浅层副本,用于防止通过内部引用结果进行不希望的访问。例如:
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。