Re: Downcasting third layer class
jstorta wrote:
I am preparing for the SCJP exam and I have run across this snipet of
code that is confusing me.
1. class Alpha { void m1() {} }
2. class Beta extends Alpha { void m2() { } }
3. class Gamma extends Beta { }
4.
5. class GreekTest {
6. public static void main(String [] args) {
7. Alpha [] a = {new Alpha(), new Beta(), new Gamma() };
8. for(Alpha a2 : a) {
9. a2.m1();
10. if (a2 instanceof Beta || a2 instanceof Gamma)
Note that the second part of this test is redundant.
If the object is a Gamma, it is also a Beta so the first
instanceof yields true and the second is never attempted.
If the object is not a Beta, it is also not a Gamma, so
if the first instanceof yields false, so will the second.
Either way, the result of the first instanceof is the
result of the entire expression.
11. a2.m2();
12. ((Beta)a2).m2();
13. ((Alpha)a2).m2();
14. ((Gamma)a2).m2();
15. }
16. }
17. }
The way I see this there are three levels of inheritance
Alpha
+------Beta
+------Gamma
I can understand why lines 11 and 13 fail to compile. Both are
instances of Alpha trying to call an m2() method, which type Alpha
does not have.
I can also understand why line 12 is fine. It is being explicitly
cast to type Beta, which does have an m2() and therefore works fine.
My confusion is with line 14. This line compiles but throws a
ClassCastException at runtime.
Since Gamma extends Beta and Beta contains an m2() method, then Gamma
should also contain an m2() method. Right? The method is not private
in Beta so it should be inherited.
Right.
Why can I cast to Beta with no problem, but not to Gamma?
Because a[1] is not a Gamma, and you cannot just pretend
that it is one. As it happens, you only care about its Beta-
ish aspects -- but that's not the issue. The issue is that
you have told Java "You already know that the object is an
Alpha, but I happen to know that it is also a Gamma." Java
says "Interesting, if true -- I'll just take a quick look,"
and discovers that you were wrong: The object is not a Gamma.
If the object were in truth a Gamma, Java would next hunt
for its m2() method and would discover that m2() is inherited
from Beta. But Java never gets that far: As soon as it finds
that you were wrong about the nature of the object, it bails
out with a ClassCastException.
--
Eric Sosman
esosman@ieee-dot-org.invalid