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.
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...
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...
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...
Joined: Mar 13, 2006
I'm still not 100% clear.
What does 'casting down the hierarchy' mean in the above example?
Joined: Sep 12, 2005
visualize it ......
class FourWheeler implements DrivingUtilities
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...
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.
--- Palette surgeonfish and Blue tang are the same