Tag: incovertible types

Reference Variable casting in Java

Hi,

In this article today, I will try to explain the types of casting allowed in java and the reasons why we face the java.lang.ClassCastException during runtime and how it is bypassed during compile time.

Before we start, let us understand two important points:

1. A reference type of parent class can point to an object of child class but the reverse is not true i.e., a reference of child type cannot point to an object of parent type.

class Animal { …. }

class Dog extends Animal { …. }

Animal animal = new Dog(); //Works fine because Dog IS-A Animal

Dog dog = new Animal(); //Not allowed by compiler because Animal IS-A //Dog is not true

2. When reading the below line:

Type1 reference = new Type2();

If the above syntax is valid, read it from right-to-left i.e., the relation between the two types here can be mentioned as “Type2 IS-A Type1” which means anything that can be performed using object of Type1 can be replaced with an object of Type2.

Downcasting:

Now coming to casting, java allows a variable to be casted to the type of a sub-class (downcasting) or to the type of a super-class (upcasting) but there are scenarios where this will lead to run-time exception.

Example for Downcasting: Consider we have the below hierarchy tree

class Animal { void animalBehavior() { …. } }

class Dog extends Animal { void dogBehavior() { …. } }

Now look at the below two scenarios.

Scenario-1

Animal animal = new Dog();

Dog dog = (Dog) Animal;

dog.dogBehavior();
Scenario-2

Animal animal = new Animal();

Dog dog = (Dog) animal;

dog.dogBehavior();

When we try to compile and run the above two scenarios, scenario-1 works fine whereas scenario-2 fails during run-time.

Q) How did the two scenarios compile fine without compiler reporting any error? (considering the #1 discussed in the introduction)

A) The answer is given by the compiler. When the above scenarios are compiled, all the compiler checks is that whether the two types (Animal & Dog) fall in the same inheritance tree. Since they do appear in the same inheritance tree, compiler did not say anything. The two types can appear in the inheritance tree in either way, it doesn’t matter to the compiler.

Q) Why did scenario-2 fail during run-time?

A) The answer is explained in #1 and #2 scenarios above. A child reference cannot point to an object of the parent type and if we infer what we are doing in scenario-2, we will come to the statement that “Animal IS-A Dog” which is not true i.e., Animal object cannot do everything that can be done by an object of Dog.

Upcasting:

Unlike downcasting, upcasting which is casting up the inheritance tree works implicitly. When you upcast, you are restricting the number of methos you can invoke as opposed to downcasting.

Dog dog = new Dog();

Animal animal = dog; //no explicit cast, works by default

Animal animal = (Animal) dog; //explicit cast 

animal.animalBehavior();

Points to Note:

  1. Casting only works when the casted object follows an “IS-A” relationship to the type you are trying to cast to.
  2. If the compiler knows for certainity that the cast does not work, it will report a compilation error as “inconvertible types”.

References:

https://www.ibm.com/developerworks/community/blogs/738b7897-cd38-4f24-9f05-48dd69116837/entry/classcastexception_reason_and_resolution2?lang=en