Search code examples
javacloning

Overriding Clone() method in Java when superclass is not Clonable


How to clone a Java object with the clone() method

I have a question regarding properly implementing the clone() method for a class in java. I know that this is bad practice, but I need to know this for an exam.. In the above discussion they say to call super.clone() - but I don't udnerstand what happens if the super function doesn't implement Clonable. For example, say I have a class X that extends Y. X implements Clonable and Y doesnl't. Y's clone() method should throw an Exception. Then what do we do in this case?

All the explanations I could find somehow assume that all superclasses implement Clonable, or at least that's what I understood..

EDIT:

Check out this code please:

public class Employee implements Cloneable {

private String name;

public Employee(String name) {
    this.name = name;
}

public String getName() {
    return name;
}

public Object clone()throws CloneNotSupportedException{  
    return (Employee)super.clone();  
}

public static void main(String[] args) {
    Employee emp = new Employee("Abhi");
    try {
        Employee emp2 = (Employee) emp.clone();
        System.out.println(emp2.getName());
    } catch (CloneNotSupportedException e) {
        e.printStackTrace();
    }
}

}

It is taken from here: https://www.javacodegeeks.com/2018/03/understanding-cloneable-interface-in-java.html

Similar code can be found in many tutorials.

Why can they use super.clone() when the superclass (which in this case is Object) does not implement Clonable - that would result in an Exception.


Solution

  • If you have this structure:

    class Y {}
    
    class X extends Y implements Cloneable {
        @Override
        public X clone() {
            try {
                return (X) super.clone();
            } catch (CloneNotSupportedException e) {
                throw new InternalError(e);
            } 
        }
    }
    

    Then clone on instances of X will work fine. It won't work on direct instances of Y, because they are not declared cloneable. But the Cloneable interface on X is an indicator to the mechanisms of the default clone() implementation that they should be made to work.

    Alternatively

    You could also have a non-Cloneable class with a working clone() method, as long as you didn't rely on the default implementation of clone().

    For instance:

    class Y {
        @Override
        public Y clone() {
            // Don't call super.clone() because it will error
            return new Y(...); // whatever parameters
        }
    }
    

    However, with this mechanism, if you called super.clone() from a subclass of Y, you would get an instance of Y, which is probably not what you would want.

    As others have pointed out, the Cloneable mechanism is awkward and confusing, and usually copying mechanisms using new are easier to work with.