Question

This is an example of defensive copy in Effective java. Assume that scenario's in my underlying questions need a defensive copy, and cannot do with a comment asking client to avoid mutating objects passed in.

public Period(Date start, Date end) {
    this.start = new Date(start.getTime());
    this.end = new Date(end.getTime());
}

Questions:

  1. What to do if Date did not have a constructor to take itself in, to make my self more general, an object is passed with no mechanism to replicate itself, and such object does not belong to us, ie we cant change it in any way ?

  2. What if the constructor took type parameter as an argument, say Period(T object) and T could be mutable so needs defensive copy. We dont have any idea of what is T. How to do defensive copy in this case ?

  3. What is an interface is passed where some of its subclasses do have a constructor like Date to create an object of itself and some of its subclasses dont have any mechanism to do so ?

  4. How deep should we defensively copy ? Lets say we copy an array, but array elements were mutable ?

Was it helpful?

Solution

  1. If all its state is available, you can extract its state and construct a new object by yourself. Otherwise, you can't do anything about it except using nasty reflection or serialization tricks.
  2. If T is not an instance of a class that allows copying itself, you can't do anything.
  3. You can't do anything about it.
  4. It depends.

By reading your question, it looks like you would like to apply the "defensive copy" advice everywhere. You shouldn't. Most of the time, code using mutable objects want a reference to the original object, and not a copy. Especially if what you get as argument is an instance of an abstract class or interface.

You're forced to make a defensive copy of Date because it's mutable value type that shouldn't be mutable, and wouldn't be if it had been properly designed. If you promote immutability for value types, then defensive copies become unnecessary. For non-value types, you generally don't want a copy, but a reference to the object.

OTHER TIPS

  1. If you can't change object's state anyway, you don't need a defensive copy.
  2. The only thing you can do is assume probable implementation of T and check them with instanceOf.
  3. Same as 2.
  4. At your discretion. If you assume that modification of array elements could break your program in another places, you should copy them all too.

Defensive programming matters when the objects you pass to a method is mutable. A good practice (also described in the Effective Java book) is to make them immutable.

  1. If the Date class is not final, you can write a wrapper class for it, that is subclass of Date.
  2. It depends. Probably, there will be no need to clone it.
  3. It shouldn't bother you. The implementor of an interface should take care of synchronization issues. Generally, it is a good practice to pass interfaces instead of their implementations.
  4. For standard java collections there are a lot of utility methods in the java.util.Collections class, such as unmodifiableList and unmodifiableMap, intended to use for defensive programming.
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top