Search code examples
javaclonecloneable

What is this field-by-field copy done by Object.clone()?


In Effective Java, the author states that:

If a class implements Cloneable, Object's clone method returns a field-by-field copy of the object; otherwise it throws CloneNotSupportedException.

What I'd like to know is what he means with field-by-field copy. Does it mean that if the class has X bytes in memory, it will just copy that piece of memory? If yes, then can I assume all value types of the original class will be copied to the new object?

class Point implements Cloneable{
    private int x;
    private int y;

    @Override
    public Point clone() {
        return (Point)super.clone();
    }
}

If what Object.clone() does is a field by field copy of the Point class, I'd say that I wouldn't need to explicitly copy fields x and y, being that the code shown above will be more than enough to make a clone of the Point class. That is, the following bit of code is redundant:

@Override
public Point clone() {
    Point newObj = (Point)super.clone();
    newObj.x = this.x; //redundant
    newObj.y = this.y; //redundant
}

Am I right?

I know references of the cloned object will point automatically to where the original object's references pointed to, I'm just not sure what happens specifically with value types. If anyone could state clearly what Object.clone()'s algorithm specification is (in easy language) that'd be great.


Solution

  • Yes, a field by field copy does mean that when it creates the new (cloned) object, the JVM will copy the value of every field from the original object into the cloned object. Unfortunately this does mean that you have a shallow copy. If you desire a deep copy, you can override the clone method.

    class Line implements Cloneable {
    
        private Point start;
        private Point end;
    
        public Line() {
            //Careful: This will not happen for the cloned object
            SomeGlobalRegistry.register(this);
        }
    
        @Override
        public Line clone() {
            //calling super.clone is going to create a shallow copy.
            //If we want a deep copy, we must clone or instantiate
            //the fields ourselves
            Line line = (Line)super.clone();
            //assuming Point is cloneable. Otherwise we will
            //have to instantiate and populate it's fields manually
            line.start = this.start.clone();
            line.end = this.end.clone;
            return line;
        }
    }
    

    Also one more important thing about the cloning is, the constructor of the cloned object is never invoked (only the fields are copied). So if the constructor initializes an external object, or registers this object with some registry, then that will not happen for the cloned object.

    I personally prefer to not use Java's cloning. Instead I usually create my own "duplication" methods.