Win a copy of The Java Performance Companion this week in the Performance forum!
  • Post Reply
  • Bookmark Topic Watch Topic
  • New Topic

Casting down the hierarchy

 
d jones
Ranch Hand
Posts: 76
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi

I got the following question from about.com but I don't fully understand the answer.

class FourWheeler implements DrivingUtilities
class Car extends FourWheeler
class Truck extends FourWheeler
class Bus extends FourWheeler
class Crane extends FourWheeler

Consider the following code below:
1. DrivingUtilities du;
2. FourWheeler fw;
3. Truck myTruck = new Truck();
4. du = (DrivingUtilities)myTruck;
5. fw = new Crane();
6. fw = du;

Then the following statemnt is considered true:
The code will not compile without an explicit cast at line 6, because going down the hierarchy without casting is not allowed.

Why do they say that we are casting down the hierarchy at line 6.
fw is a reference varaiable for a FourWheeler object.
du is a reference variable which stores a reference to an object implementing the DrivingUtilities interface.

fw can refer to any of its subclasses which implement the du interface. Why would the compiler complain about this? I would have thought that it should compile okay and throw a ClassCastException if there were a problem.

Many Thanks
 
Charith Fernando
Ranch Hand
Posts: 67
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
take Object and String as an example....

Object is the super class and the String is the sub class....

if you want to assign a String to an Object you dont need a cast. because simply you can assign any subclass to a reference of one of it's superclasses...



when you want to convert this 'a' into a String or when you want to assign the object to a String reference as follows, then you need a cast...

WHY?

because at compile time, the compiler is not aware of the object it holds and therefore needs a cast to say... "I know this reference holds a String for sure" to ensure this you can run an instanceof condition.

the compiler only worries about the reference type not the object type....

a ClassCastException may occur if you assign an Integer to an Object reference and try to cast it to a String.

if you try to do this, you wont get any compilation errors because at compile time JAva just checks whether it can convert an Object to a String.. but at real or at runtime the real Object is an Integer.. and an Integer cannot be casted to a String...

ask if its not clear....
 
Charith Fernando
Ranch Hand
Posts: 67
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
just thought i would add some more....

JUST dont worry about the Objects which a reference holds at compile time.. just concentrate on the reference variable types at compile time... if you just think like in this way then you would know whether the code will compile or not... if the code tries to assign an Object reference to a String reference you always need a cast because the compiler does not gaurantee that whats in there in that reference is really a String...

at RUNTIME: think about the Objects.. if the Object reference held an Integer and if you try to cast it to a String then a ClassCastException may get thrown...

though the following code does not work at runtime it will compile fine...

 
d jones
Ranch Hand
Posts: 76
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Thanks Charith

I'm still not 100% clear.

What does 'casting down the hierarchy' mean in the above example?

Many Thanks
 
Charith Fernando
Ranch Hand
Posts: 67
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
visualize it ......

class FourWheeler implements DrivingUtilities

means

FourWheeler ---- >>>>> DrivingUtilities

and you're trying to assing a 'DrivingUtilities' reference into a FourWheeler reference... so think who's at the top of the hierarchy...

DrivingUtilities is in the top and FourWheeler is in the bottom.. which means if you're trying to assign a superclass reference into a subclass reference you're you need to cast it... or down cast it...

hope you got it
 
marc weber
Sheriff
Posts: 11343
Java Mac Safari
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
See if these topics from Bruce Eckel's Thinking in Java help:
  • Upcasting
  • Downcasting and run-time type identification
  •  
    David Kennedy
    Ranch Hand
    Posts: 33
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Im wondering is the Cast at line 4 necessary.
    Im guessing that it isnt?

    and you could just do


    du=mytruck;
     
    Burkhard Hassel
    Ranch Hand
    Posts: 1274
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Hi cowboys,


    if the last line were
    fw = (FourWheeler)du;


    It would compile.

    Special service for home tests:


    compiles and runs without exception

    du is of reference type DrivingUtilities (the reference type of the interface) it stores an object that was a Truck. That's possible, since Truck IS-A DrivingUtility (Truck extends FourWheeler and 4Weeler implements D.Ut.).

    fw is of reference type FourWheeler. In the last but one line, fw stored a Crane object, but that's not important. In the last line fw is dereferenced to the du variable.
    It needs an explicit cast, because du is of an interface type.

    If you cast from implementer to interface, it is an upcast.
    The other way round is a downcast, that needs an explicit cast.




    Easier example, castings between interfaces an implementers



    In the upper example, you can cast implicitely from an implementer to its interface. It is always clear, that a class that implements an interface also has its methods.

    But in the example with variable sandy, you have to cast manually. Otherwise, the code would not compile. It is not sure, that a Swimable IS-A BlueTang. Could also be a ClownFish or a Dolphin.


    That you have to put a casting manually makes sense, since it is possible that such a interface -> implementer casting could cause a class cast exception (what the code here does not do).

    But if you set up a class, say ClownFish, that implements Swimable, and you wrote:
    ClownFish nemo = (ClownFish) swimmer;
    you get a ClassCast Exception. Because swimmer stored a BlueTang, not a Clowny.




    Yours,
    Bu.


    ---
    Palette surgeonfish and Blue tang are the same
     
    marc weber
    Sheriff
    Posts: 11343
    Java Mac Safari
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Originally posted by David Kennedy:
    Im wondering is the Cast at line 4 necessary.
    Im guessing that it isnt? ...

    That's correct. But there's no need to guess. A quick test will confirm...
     
    • Post Reply
    • Bookmark Topic Watch Topic
    • New Topic