2

Does anyone have any workable strategy for solving casting/upcasting questions? I understand when upcasting and downcasting is allowed but when the questions tend to have multiple objects involved i tend to get confused pretty quickly. For example, what is the best approach to finding the answer to a question like this:

Question: What would be the result of compiling the following program:

interface Inter{}
class Base implements Inter{}
class Derived extends Base{}

class ZiggyTest2{

    public static void main(String[] args){

        Base b = new Base();
        Derived d = new Derived();
        Inter i = (Base)b;
        i = (Base)d;
        Derived bd = (Derived)b;
        b = (Base)i;        
    }   
}

I am not really interested in the answer but more the approach to solve the question. Is there any approach/strategy i can use to solve an upcasting/downcasting question like above? For example can the references/objects be drawn on paper so that i can get a visual representation and can that help?

Thanks

ziggy
  • 15,677
  • 67
  • 194
  • 287

4 Answers4

3

There are some simple rules

  • You can cast to class predescessor (all the way to Object) (never fais)
  • You can cast to subclass - this can fail at runtime
  • You can cast to interface from class that implements it (never fails)
  • You can cast from interafce to iplemneting class - this can fail at runtime

first two rules applies ti intefaces as well.

You can draw UML class diagram to visualise it (with only implements = realizes, extends realetions), navigating through the graph would be safe in the direction of the arrows. Navigating the other way would be run-time usafe. And navigating without extends/implements relation would be impossible.

Hurda
  • 4,647
  • 8
  • 35
  • 49
3

Here is a great article about upcasting and downcasting.

Quote from the article --

First, you must understand, that by casting you are not actually changing the object itself, you are just labeling it differently.

Just ask yourself the question "what is the type of the object?" and then remember that it is legal to cast it to any predecessor class in the class heirarchy (including interfaces).

In your case, you are creating 2 objects, a Base and Derived. The Base can be labeled an Inter or a Base and the Derived can be labeled an Inter, Base or Derived. So, your code will compile just fine. But at runtime, when you try to cast Base b to a Derived bd, you will get a ClassCastException.

Kal
  • 24,724
  • 7
  • 65
  • 65
1

If the objects being operated are in the same hierarchy, casting will compile for sure, but it might fail at runtime.

E.g.:

class Animal { }
class Dog extends Animal { }
class Bulldog extends Dog { }

If you write:

Animal animal = new Animal();
Dog d = (Dog) animal;

Above code will compile, but it will fail at runtime. Because all the compiler can do is check if the two types are in the same inheritance tree. Compiler allows things which might work at runtime. But if the compiler knows for sure that something will never ever work, it will throw error at runtime itself. E.g.

Animal animal = new Animal();
Dog d = (Dog) animal;
String s = (String) animal;

This will surely fail as the compiler knows that String and Dog are not in the same hierarchy.

The same rules apply to interfaces as well.

Hope it helps.

Bhushan
  • 18,329
  • 31
  • 104
  • 137
1

For me I'd like to first draw the hierarchy of these types. For your question, the "levels" of the types are:


Inter (is higher than)

Base (is higher than)

Derived


The "level" of an object is determined at its creation, and the object can only "go" up not down depending on its creation level. For example, Object b is created as a Base object, so it is at the level of Base. You can easily find out b can upcast to Inter but not downcast to Derived, no matter what type is used to describe b. If Inter is used to describe b, since its creation level is Base, you can downcast it to Base.