Casting Reference Variables- Downcasting, Upcasting

Let us consider two classes class Animal, a more generic class and class Cat, a more specific class i.e a more specific animal. Let us settle for simple definitions for both the classes so as to get the concept right.

/*
The definition for more generic class Animal
Notice the eat() method, which will be inherited by all Classes extending Animal
*/

class Animal
{

public void eat()
{

System.out.println(“Animal  Eating“);

}

}

/*
Definition for more specific Animal i.e Cat, extends Animal
Notice the overridden eat() method and an extra method goHunting()
*/

class Cat extends Animal
{

public void goHunting()
{

System.out.println(“Do Cat related Hunting”);

}

/*
Overridden eat() method
*/

public void eat()
{

System.out.println(“Cat specific Eating”);

}

}

With a Animal reference pointing to Animal object on the heap one can access only the eat() method of Animal class.

With a Animal reference pointing to Cat object on the heap one can access the overridden version of eat() method in the Cat class (Polymorphism at work here), but even though the object has goHunting() method it cannot be invoked using a reference of type Animal.

With a reference of type Cat pointing to Cat object on the heap, its a pretty straight forward one.

Suppose there is a method getAppointment() in class Veterinarian which has to work for all arguments of type Animal, then the parameter is declared as a more generic Animal.

If I pass a Cat object to the method and try to access the goHunting() method there would be a compiler error “Cannot Find Symbol”. So one has to cast the object passed into Cat and then access the method. The following code snippet explains the thing.

/*
The class Veterinarian definition
The definition and the method definition are fictitious. May not be practical
But they are syntactically correct
*/

public class Veterinarian
{

String name;
public Veterinarian(String name)
{

this.name=name;

}
public static void main( String [] args)
{

Cat c = new Cat();
Veterinarian vet = new Veterinarian(“Dr. XXXXXX“);
vet.getAppointment(c);

}
public void getAppointment(Animal a)
{

Cat c = (Cat) a;
c.goHunting();

}

}

The casting done in the above code snippet is called “Down Casting“. Down Casting is nothing but casting down the inheritance tree to a more specific class i.e casting a superclass to subclass.

Down casting has to be done carefully as it can lead to run time exception java.lang.ClassCastException. There’s some danger lurking in the above code snipet. Can you find it out? Yeah you are right. The casting has been done without considering the fact that the object passed is a Cat or not. If i pass a Dog object and try to cast it into Cat, compiler would say you are doing correct thing. But the code blows up at run time. So before casting it has to be checked whether the passed object it as instance of the class to which we are going to cast. The above getAppointment() method can be modified into a more safer code below:

public void getAppointment(Animal a)
{

if ( a instanceof cat)
{

Cat c = (Cat) a;
c.goHunting();

}

}

There are some places where casting fails at compile time itself.

Animal a = new Animal();
Cat c = (Cat)a;//Blows up at Run time

String s  = (String) a; //Compiler will kill you for doing this. Compiler Error

Upcasting:
Upcasting- casting up the inheritance tree to a more general type. It is done implicitly (i.e typing in the cast is not required). Its because the classes at lower level of hierarchy have all those features that are present in the classes above them in the inheritance hierarchy. So they can be upcasted implicitly ( like Dog IS-A Animal).

16 thoughts on “Casting Reference Variables- Downcasting, Upcasting”

  1. This is not the end of the story!
    Given Animal myAnimal= new Cat(); // cat extends animal ok!
    Does Cat felix = myAnimal; //work? No it does not!
    or Cat felix = (Cat)myanimal; //Yes it does !
    if you run
    public static void main(String[] args) {
    Animal myAnimal = new Cat();

    Boolean b =myAnimal instanceof Cat;// The great power of Autoboxing!
    if(b){
    System.out.println(“myAnimal is a cat = “+ b) ;
    }
    else{
    System.out.println(“I hate dogs”) ;
    }
    }

    you get : myAnimal is a cat = true!
    Why we need a cast ? Find it out yourself!

    Reply

Leave a Reply

Discover more from Experiences Unlimited

Subscribe now to keep reading and get access to the full archive.

Continue reading