Search code examples
javaoopclone

Don't think I'm getting .clone()


Let's say I have a class called House with two fields:

  • int area
  • java.util.Date whenBuilt

I would like to perform a deep copy of this class using clone() by overriding the clone method in the Object class:

public Object clone() throws CloneNotSupportedException {
    // Perform a shallow copy
    House houseClone = (House)super.clone();
    
    // Deep copy on whenBuilt
    houseClone.whenBuilt = (java.util.Date)(whenBuilt.clone());
    
    return houseClone;
}

Apparently the code above is how this should be done. What I don't understand is this: Doesn't writing whenBuilt.clone() do a shallow copy of the Date object and not a deep copy? In other words, wouldn't my houseClone's whenBuilt field still refer to my original House class and its whenBuilt field? My understanding is that all clone methods, by default, don't do deep copies. What am I not getting?


Solution

  • The instance contains two values. You need to copy those values from the original to the new instance. It would be something more like:

    public Object clone() throws CloneNotSupportedException {
        // Perform a shallow copy
        House houseClone = (House)super.clone();
        
        // Deep copy on whenBuilt and area
        houseClone.whenBuilt = (java.util.Date)(this.whenBuilt.clone());
        houseClone.area = this.area;
         
        return houseClone;
    }
    

    We know that a date is a pretty simple object, and you could just construct a new date with the time value from the old date, however if the clone method on Date works then it would be in general more proper to use it.

    Doesn't writing whenBuilt.clone() do a shallow copy of the Date object and not a deep copy?

    Clone is for doing deep copy. Apparently the precise meaning depends on the class. It is supposed to given you another instance which has all the same values, but is a different instance. If you examine the code for the Date class, you find it only holds a single long value, so there is no real difference between shallow and deep for the Date class.

    If you don't do clone on the Date object, then both House objects, the original and the cloned will point to the same instance of Date. The clone operation will give you a new instance of Date, with the same date value within it. Date objects have mutator methods, like setDate and you would not want a setDate on one house to change the date of the other house, so you have to clone them.