7

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!

Joran Den Houting
  • 3,149
  • 3
  • 21
  • 51
Hesham Yassin
  • 4,341
  • 2
  • 21
  • 23

1 Answers1

10

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.

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • That's the reason why a clone method implementation should NEVER directly create the copy via new but should ALWAYS use super.clone() instead! Otherwise it is impossible to correctly override clone in subclasses! – isnot2bad Sep 27 '13 at 09:34
  • Thanks for the detailed answer...When I debugged the code, the next code line: B a = (B) super.clone(); sent me to A.clone() which returns instance of A..so i don't understand how super.clone() return a B? – Hesham Yassin Sep 27 '13 at 09:37
  • 2
    @HeshamYassin: No, `A.clone()` returns a reference which is *at least* an `A` - that's what's guaranteed by the cast to `A`. But it will *actually* be a `B` (or a subclass), because you're cloning an instance of `B`. Look at the value of `ac` in the debugger, and you'll see it's a reference to an instance of `B`. – Jon Skeet Sep 27 '13 at 09:40