Let's suppose we have this code:
public class C {}
public class D extends C {}
That is, everything that is a D
, is also a C
. But the reverse is not necessarily true.
And then this:
D d = (D) (C) new D();
What is a concise way of writing what can be interpreted with these four steps:
D temp1 = new D(); // Etapa 1
C temp2 = (C) temp1; // Etapa 2
D temp3 = (D) temp2; // Etapa 3
D d = temp3; // Etapa 4
What each step does:
new D()
creates an object of type D
.
The cast for C
checks to see if the object is of type C
. Since the compiler knows that all D
is C
, then this cast is valid. The resulting subexpression is of type C
.
The cast for D
checks to see if the object is of type C
. Because the compiler knows that not all% is_ is a C
, then a check will be done at runtime. If the object of type D
is not a C
, a D
is thrown. In this case, this check will always succeed. The resulting subexpression is of type ClassCastException
.
The resulting value is assigned to the D
variable. Since the compiler knows that what is to the right of the d
sign is of type =
and the D
variable is also of type d
, then this assignment is valid.
Notice that there are two types of casts here. One of them (the one in step 2) is an upcasting and the other one (step 3) is a downcasting . See more about this on this other question .