是否应该为传递给构造函数的可变对象的对象引用设置防御副本?
如果是,那么我应该如何“深入”制作副本。在下面的示例中,我应该在所涉及的所有类的副本构造函数中进行深层复制吗?
例如:
class Graph {
AdjacencyList;
public Graph(Graph graph) {
this.list = graph.list; // shallow copy
OR
this.list = ArrayCopy(graph.list); // deep copy
}
}
class DFS implements GraphAlgo {
Graph g
DFS(Graph g) {
this.g = g; // shallow copy
OR
this.g = new Graph(graph) // deep copy
}
DFS(Algo algo) {
this.g = algo.g; // shallow copy
OR
this.g = new Graph(algo.g); // deep copy
}
}
class Algo {
GraphAlgo galgo
Algo (GraphAlgo dfsalgo) {
galgo = dfsalgo // shallow copy
OR
galgo = new DFSAlgo(dfsalgo); // deep copy
}
}
3 ..如果有些课忘记实施深拷贝怎么办?这是否意味着我永远不会有一个安全的深度复制对象?有什么方法可以防止这种情况吗?
答案 0 :(得分:5)
你应该防守吗?
只有你需要。
你要去多深?
尽可能深入。
声音陈腐?那么,这类问题的基本答案是“尽可能少地提供所需的功能”。
答案 1 :(得分:2)
一般情况下:除非您不信任主叫代码,否则不要制作防御性副本。
执行:记录界面,并说如果这会导致问题,则不允许他们更改通过您的任何内容。
有时:提供两个构造函数。一个使用该对象。一个人复制。然后让调用者在需要时调用复制者。在调用构造函数后,调用者可能会丢弃对该对象的任何引用。在这种情况下,不需要复制。
Algo (GraphAlgo dfsalgo, boolean doCopy) {
if (doCopy) {
galgo = new DFSAlgo(dfsalgo); // deep copy
} else {
galgo = dfsalgo // shallow copy
}
}
如果您信任调用代码:忽略此问题。期望它在调用你的代码之前复制它不会丢弃的东西(从它自己的角度来看)。
偏执狂并不意味着他们不能帮助你。但这并不意味着他们也是。