Java downcast in clone

Lets say that Class B extends class A and class A is Cloneable as follows:

public class A implements Cloneable {
    public Object clone() throws CloneNotSupportedException {
        A ac = (A) super.clone();
        return ac;
    }
}

public class B extends A {
    public Object clone() throws CloneNotSupportedException {
        B a = (B) super.clone();
        return a;
    }
}

Why it is legal to perform down-cast from A to B in the next line:

B a = (B) super.clone(); // (super of B is A)

while the next down-cast is run-time error?

A a = new A();
B b = (B) a.clone();

Thanks in advance!

Jon Skeet
people
quotationmark

Ultimately, this is using Object.clone() to create the object - and that's guaranteed to create a new object of the same execution-time type as the object it's called on:

The method clone for class Object performs a specific cloning operation. First, if the class of this object does not implement the interface Cloneable, then a CloneNotSupportedException is thrown. Note that all arrays are considered to implement the interface Cloneable and that the return type of the clone method of an array type T[] is T[] where T is any reference or primitive type. Otherwise, this method creates a new instance of the class of this object and initializes all its fields with exactly the contents of the corresponding fields of this object, as if by assignment; the contents of the fields are not themselves cloned. Thus, this method performs a "shallow copy" of this object, not a "deep copy" operation.

So if we get a call to clone() being executed on an instance of B, then super.clone() will return a B (or a subclass) - so the cast is valid.

In your second case, you're creating an instance of just A, which is not an instance of B, so the cast fails.

people

See more on this question at Stackoverflow