Java Defensive Copying

Defensive Copying is a term used for immutable objects.

Briefly, you cannot change the state of an immutable object once created. In Java, String class and all wrapper classes (like Boolean, Integer, Long) are immutable classes.

To create immutable class, instance fields should be made private final and there should be no setter methods.

Examine the code below for FooCalendar class. At first glance, this class seems to be an immutable class. Class is declared as final. Instance field (standardDate) is declared as private final and the class contains no setter methods.

public final class FooCalendar {
  private final Date standardDate;
  
  public FooCalendar(Date date) {
    standardDate = date;
  }

  public Date getStandardDate() {
    return standardDate;
  }
}

On the contrary, FooCalendar is mutable.

Examine the following code. Here, a new FooCalendar instance is created and originalDate is passed to its constructor.

    Date originalDate = new Date();
    FooCalendar fooCalendar = new FooCalendar(originalDate);
    originalDate.setYear(150);

Both originalDate and fooCalendar(standardDate) points to same Date object in memory. If originalDate is updated, fooCalendar(standardDate) is updated as well. This makes FooCalendar class mutable.

Mutable fooCalendar Instance

To overcome this problem, a copy of originalDate should be created in FooCalendar constructor and standardDate should be assigned to this copy.

  // FooCalendar constructor
  public FooCalendar(Date date) {
    // A new copy of date is created and standardDate points to this copy.
    standardDate = new Date(date.getTime());
  }

Defensive Copying

Creating a copy of Date object in FooCalendar constructor resolves part of the problem. Still, standardDate field of FooCalendar class can be accessed from outside. See the code below.

  Date dateReference = fooCalendar.getStandardDate();
  dateReference.setYear(150);

In the first line, we get reference to standardDate field of fooCalendar object and assign it to dateReference variable. In the second line, dateReference is updated. Since both dateReference and standardDate are referring to same Date object, fooCalendar is also updated. This breaks immutability of FooCalendar class.

Solution is simple. We can change getStandardDate() method, such that it returns a copy of standardDate.

  public Date getStandardDate() {
    return new Date(standardDate.getTime());
  }

To sum up, if you want to ensure mutability of the class and it has mutable fields (like java.util.Date), then you should use defensive copying. That is, parameters should be copied in constructor and getter methods should return a copy the field rather than the field itself.

SHARE