Ultimately, this uses Object.clone() to create the object - and this guarantees the creation of a new object of the same type of runtime as the object that it named on:
The clone method for the Object class performs a specific clone operation. First, if the class of this object does not implement the Cloneable interface, then a CloneNotSupportedException . Note that all arrays are thought to implement the Cloneable interface and that the return type of the clone method of the 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 the exact contents of the corresponding fields of this object, as if it were assigned; the contents of the fields are not cloned per se. Thus, this method performs a “shallow copy” of this object, and not a “deep copy” operation.
So, if we get the clone() call executed on instance B , then super.clone() will return B (or a subclass) - so the action will be valid.
In your second case, you only create an instance of A , which is not an instance of B , so the failure is executed.
source share