5
  1. Should defensive copies always be made for object references of mutable objects passed to constructors ?

  2. If yes, then how 'deep' should I go in making copies. In the following example should I make deep copies inside copy constructors of all classes involved ?

Eg:

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.. What if some class forgets to implement deep copy ? Does it mean I will never have a safe deep copied object ? Any way to prevent this ?

JavaDeveloper
  • 5,320
  • 16
  • 79
  • 132

2 Answers2

5

Should you be defensive?
Only if you need to be.

How deep should you go?
As deep as you need to.

Sound trite? Well, the basic answer to these type of questions is "do as little as you need to do to deliver the required functionality".

Bohemian
  • 412,405
  • 93
  • 575
  • 722
2

Generally: Don't make defensive copies unless you don't trust the calling code.

Do: Document the interface and say that they aren't allowed to change anything they pass you if that's going to cause a problem.

Sometimes: Provide two constructors. One uses the object. One makes a copy. Then let the caller call the one that makes a copy when needed. The caller may well discard any reference to that object just after calling your constructor. In that case, no copy is needed.

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

If you trust the calling code: Ignore the issue. Expect it to make copies of anything it isn't going to discard (from its own point of view) before calling your code.

Paranoia doesn't mean they aren't out to get you. But it doesn't mean they are either.

Lee Meador
  • 12,829
  • 2
  • 36
  • 42