5
  1. 是否应该始终为传递给构造函数的可变对象的对象引用制作防御性副本?

  2. 如果是,那么我在制作副本时应该“深入”到什么程度。在下面的示例中,我应该在所有涉及的类的复制构造函数中进行深度复制吗?

例如:

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.. 如果某些类忘记实现深拷贝怎么办?这是否意味着我永远不会有一个安全的深度复制对象?有什么办法可以防止这种情况?

4

2 回答 2

5

你应该防守吗?
仅当您需要时。

你应该去多深?
只要你需要。

听起来老套?好吧,这类问题的基本答案是“尽你所能提供所需的功能”。

于 2013-08-09T22:09:02.303 回答
2

通常:除非您不信任调用代码,否则不要制作防御性副本。

做:记录界面并说如果这会导致问题,则不允许他们更改他们传递给您的任何内容。

有时:提供两个构造函数。一个使用对象。一个人制作副本。然后让调用者在需要时调用制作副本的人。调用者很可能会在调用您的构造函数后丢弃对该对象的任何引用。在这种情况下,不需要副本。

Algo (GraphAlgo dfsalgo, boolean doCopy) {
    if (doCopy) {
        galgo = new DFSAlgo(dfsalgo); // deep copy
    } else {
        galgo  = dfsalgo  // shallow copy
    }
}

如果您信任调用代码:忽略该问题。期望它在调用您的代码之前复制它不会丢弃的任何东西(从它自己的角度来看)。

偏执狂并不意味着他们不会找你。但这并不意味着它们也是。

于 2013-08-09T22:03:56.617 回答