Downcasting third layer class

J

jstorta

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)
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.

Why can I cast to Beta with no problem, but not to Gamma?

I've looked through texts and tried to find an explanation. All of
the examples I've found only go 2 levels and that makes perfect
sense. I cannot find any explanations with 3 levels that might clear
this up for me.

I feel I am just overlooking something obvious, but I've stared at it
so long I am lost. Some guidance would be appreciated.


Thanks.
 
E

Eric Sosman

jstorta said:
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.
 
J

jstorta

OMG. The red herrings on this test are going to kill me. All along I
was convinced that there was something about inheritance that I was
not understanding.

Now, as you explained, it makes perfect sense. This whole question
was really to test if I knew the short-circuit operator. Sadly, I
know about the short-circuit operators, but I just went off on the
inheritance tangent and never looked back.

Thank you for the explanation. It was exactly what I needed.
 
J

Joe Attardi

jstorta said:
OMG. The red herrings on this test are going to kill me. All along I
was convinced that there was something about inheritance that I was
not understanding.
I took (and passed, thankfully) the test 4 years ago (worked at Sun at
the time, so thankfully I didn't have to pay for it! woot!). A lot of it
is red herrings like the one you posted, and a lot of it is purely
memorization.

Try the Rules Roundup at javaranch.com to help you prepare, I used it a
lot during my study and it helped a lot.

Good luck on the test!
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,537
Members
45,020
Latest member
GenesisGai

Latest Threads

Top