[java] How to properly override clone method?

I need to implement a deep clone in one of my objects which has no superclass.

What is the best way to handle the checked CloneNotSupportedException thrown by the superclass (which is Object)?

A coworker advised me to handle it the following way:

@Override
public MyObject clone()
{
    MyObject foo;
    try
    {
        foo = (MyObject) super.clone();
    }
    catch (CloneNotSupportedException e)
    {
        throw new Error();
    }

    // Deep clone member fields here

    return foo;
}

This seems like a good solution to me, but I wanted to throw it out to the StackOverflow community to see if there are any other insights I can include. Thanks!

This question is related to java clone cloning cloneable

The answer is


The way your code works is pretty close to the "canonical" way to write it. I'd throw an AssertionError within the catch, though. It signals that that line should never be reached.

catch (CloneNotSupportedException e) {
    throw new AssertionError(e);
}

There are two cases in which the CloneNotSupportedException will be thrown:

  1. The class being cloned does not implemented Cloneable (assuming that the actual cloning eventually defers to Object's clone method). If the class you are writing this method in implements Cloneable, this will never happen (since any sub-classes will inherit it appropriately).
  2. The exception is explicitly thrown by an implementation - this is the recommended way to prevent clonability in a subclass when the superclass is Cloneable.

The latter case cannot occur in your class (as you're directly calling the superclass' method in the try block, even if invoked from a subclass calling super.clone()) and the former should not since your class clearly should implement Cloneable.

Basically, you should log the error for sure, but in this particular instance it will only happen if you mess up your class' definition. Thus treat it like a checked version of NullPointerException (or similar) - it will never be thrown if your code is functional.


In other situations you would need to be prepared for this eventuality - there is no guarantee that a given object is cloneable, so when catching the exception you should take appropriate action depending on this condition (continue with the existing object, take an alternative cloning strategy e.g. serialize-deserialize, throw an IllegalParameterException if your method requires the parameter by cloneable, etc. etc.).

Edit: Though overall I should point out that yes, clone() really is difficult to implement correctly and difficult for callers to know whether the return value will be what they want, doubly so when you consider deep vs shallow clones. It's often better just to avoid the whole thing entirely and use another mechanism.


Just because java's implementation of Cloneable is broken it doesn't mean you can't create one of your own.

If OP real purpose was to create a deep clone, i think that it is possible to create an interface like this:

public interface Cloneable<T> {
    public T getClone();
}

then use the prototype constructor mentioned before to implement it:

public class AClass implements Cloneable<AClass> {
    private int value;
    public AClass(int value) {
        this.vaue = value;
    }

    protected AClass(AClass p) {
        this(p.getValue());
    }

    public int getValue() {
        return value;
    }

    public AClass getClone() {
         return new AClass(this);
    }
}

and another class with an AClass object field:

public class BClass implements Cloneable<BClass> {
    private int value;
    private AClass a;

    public BClass(int value, AClass a) {
         this.value = value;
         this.a = a;
    }

    protected BClass(BClass p) {
        this(p.getValue(), p.getA().getClone());
    }

    public int getValue() {
        return value;
    }

    public AClass getA() {
        return a;
    }

    public BClass getClone() {
         return new BClass(this);
    }
}

In this way you can easely deep clone an object of class BClass without need for @SuppressWarnings or other gimmicky code.


You can implement protected copy constructors like so:

/* This is a protected copy constructor for exclusive use by .clone() */
protected MyObject(MyObject that) {
    this.myFirstMember = that.getMyFirstMember(); //To clone primitive data
    this.mySecondMember = that.getMySecondMember().clone(); //To clone complex objects
    // etc
}

public MyObject clone() {
    return new MyObject(this);
}

public class MyObject implements Cloneable, Serializable{   

    @Override
    @SuppressWarnings(value = "unchecked")
    protected MyObject clone(){
        ObjectOutputStream oos = null;
        ObjectInputStream ois = null;
        try {
            ByteArrayOutputStream bOs = new ByteArrayOutputStream();
            oos = new ObjectOutputStream(bOs);
            oos.writeObject(this);
            ois = new ObjectInputStream(new ByteArrayInputStream(bOs.toByteArray()));
            return  (MyObject)ois.readObject();

        } catch (Exception e) {
            //Some seriouse error :< //
            return null;
        }finally {
            if (oos != null)
                try {
                    oos.close();
                } catch (IOException e) {

                }
            if (ois != null)
                try {
                    ois.close();
                } catch (IOException e) {

                }
        }
    }
}

As much as the most of the answers here are valid, I need to tell that your solution is also how the actual Java API developers do it. (Either Josh Bloch or Neal Gafter)

Here is an extract from openJDK, ArrayList class:

public Object clone() {
    try {
        ArrayList<?> v = (ArrayList<?>) super.clone();
        v.elementData = Arrays.copyOf(elementData, size);
        v.modCount = 0;
        return v;
    } catch (CloneNotSupportedException e) {
        // this shouldn't happen, since we are Cloneable
        throw new InternalError(e);
    }
}

As you have noticed and others mentioned, CloneNotSupportedException has almost no chance to be thrown if you declared that you implement the Cloneable interface.

Also, there is no need for you to override the method if you don't do anything new in the overridden method. You only need to override it when you need to do extra operations on the object or you need to make it public.

Ultimately, it is still best to avoid it and do it using some other way.


Use serialization to make deep copies. This is not the quickest solution but it does not depend on the type.


Sometimes it's more simple to implement a copy constructor:

public MyObject (MyObject toClone) {
}

It saves you the trouble of handling CloneNotSupportedException, works with final fields and you don't have to worry about the type to return.