- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
我的教授说它们完全不同,但我读到它们非常相似。我不知道他指的是什么上下文“不同”。如果这个问题已经得到回答,只需链接它。谢谢。
最佳答案
深拷贝:对象拷贝技术的一种:将结构体中的所有数据进行深度拷贝。生成对象深拷贝的“苛刻”方法是先序列化然后反序列化。对于树,一般来说,递归复制是一种有效的解决方案。
防御性副本:保护内部数据的操作结果。通常它是一个深拷贝或浅拷贝,用于防止通过内部引用结果进行不希望的访问。例如:
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/
拿这个: var lists:{ item1:{} ,item2:{} ,item3:{} ,item4:{} } 由于它基本上是空的,我想要一个函数(可能但不一定是 _lodash
我想更改 ng bootstrap 分页组件的样式并在 Angular 6 应用程序中使用 /deep/ 链接。以下代码工作正常,但控制台显示警告,指出该代码已被弃用。 那么,我应该如何更改它以消除警
使用 webcomponents,您可以使用 /deep/ 定位 shadowdom 的内部元素,在我尝试使用事件委托(delegate)之前它工作正常。 一个常规的点击功能将起作用: $('html
在 Swift 中,我试图实现一个单词 Trie,使用文字表示作为一系列嵌套的 NSObject。这是 Trie。 let GEENITRIE:NSObject = [ "i":[
运行 npm update 更新 package.json 中列出的项目;但是,这些项目的依赖关系仍然过时。 明显的解决方法是再次运行 npm update。有时我需要运行它 3 次以上才能使 npm
我创建了 2 级嵌套 linq 查询: var data = (from p in Departments join e in Employees on p.Id equals
首先是代码 #include typedef wchar_t* BSTR; wchar_t hello[] = L"Hello"; class _bstr_t { public: opera
我要编写一个 lisp 程序来生成十六进制数的实际值。我已经编写了一个函数,但似乎出现了 stackoverflow(深度)错误。我想知道是否有人可以指出我的错误或指导我朝着正确的方向前进。 如果没有
我想将每种类型都转换为boolean 或object type CastDeep = { [P in keyof T]: K extends K[] ? K[] : T[P] ex
我刚刚发现自己在写这个: fn init_timestamps(dir: &PathBuf, file_timestamps: &'static HashMap) { match fs::re
我有一个现有的 pybind11::array_t,需要进行复制构造。 pybind11 中是否有一个函数允许我对 array_t 进行深度复制? 我知道我可以创建一个新的 array_t,适当调整大
引用http://www.devx.com/tips/Tip/13291 ,它说我可以使用 memcpy 来复制由 sizeof() 确定的大小,但是,数组不是指向指针吗? 除了遍历数组,如何使用 m
我有多个成员(member),每个成员(member)都有一条记录,其中包含几个备注字段: Member ID Entry A Entry B 1 [memo t
$watchCollection 是否能够忽略对以 $ 开头的属性的更改?使用深度 $watch 时已经存在此行为,因为它依赖于 angular.equals 进行比较。 理想情况下,$watchCo
我有一个带有复杂键的 map - 例如,二维数组: m := make(map[[2][3]int]int) 当我在映射中插入一个新键时,Go 是否会对该键进行深度复制? a := [2][3]int
我需要查询如下所述的三个表。我了解简单的 JOIN,但是这个有点超出我的水平。 courses 有两列 id (PK) 和 courseTitle(示例 id 1,courseTitle 物理) cl
我有一个对象,它是 Realm 的 Object 子类,并且符合 Codable 以便在与 API 对话时与 JSON 相互转换。 如何利用 Codable 协议(protocol)进行深度复制(包括
我是一名优秀的程序员,十分优秀!