[java] What is the difference between up-casting and down-casting with respect to class variable

What is the difference between up-casting and down-casting with respect to class variable?

For example in the following program class Animal contains only one method but Dog class contains two methods, then how we cast the Dog variable to the Animal Variable.

If casting is done then how can we call the Dog's another method with Animal's variable.

class Animal 
{ 
    public void callme()
    {
        System.out.println("In callme of Animal");
    }
}


class Dog extends Animal 
{ 
    public void callme()
    {
        System.out.println("In callme of Dog");
    }

    public void callme2()
    {
        System.out.println("In callme2 of Dog");
    }
}

public class UseAnimlas 
{
    public static void main (String [] args) 
    {
        Dog d = new Dog();      
        Animal a = (Animal)d;
        d.callme();
        a.callme();
        ((Dog) a).callme2();
    }
}

This question is related to java casting class-variables downcast upcasting

The answer is


Upcasting and downcasting are important part of Java, which allow us to build complicated programs using simple syntax, and gives us great advantages, like Polymorphism or grouping different objects. Java permits an object of a subclass type to be treated as an object of any superclass type. This is called upcasting. Upcasting is done automatically, while downcasting must be manually done by the programmer, and i'm going to give my best to explain why is that so.

Upcasting and downcasting are NOT like casting primitives from one to other, and i believe that's what causes a lot of confusion, when programmer starts to learn casting objects.

Polymorphism: All methods in java are virtual by default. That means that any method can be overridden when used in inheritance, unless that method is declared as final or static.

You can see the example below how getType(); works according to the object(Dog,Pet,Police Dog) type.

Assume you have three dogs

  1. Dog - This is the super Class.

  2. Pet Dog - Pet Dog extends Dog.

  3. Police Dog - Police Dog extends Pet Dog.

    public class Dog{ 
       public String getType () {
          System.out.println("NormalDog");
          return "NormalDog";
       }
     }
    
    /**
     * Pet Dog has an extra method dogName()
     */   
    public class PetDog extends Dog{ 
       public String getType () {
          System.out.println("PetDog");
          return "PetDog";
       }
       public String dogName () {
          System.out.println("I don't have Name !!");
          return "NO Name";
       }
     }
    
    /**
     * Police Dog has an extra method secretId()
     */
    public class PoliceDog extends PetDog{
    
     public String secretId() {
        System.out.println("ID");
        return "ID";
     }
    
     public String getType () {
         System.out.println("I am a Police Dog");
         return "Police Dog";
     }
    }
    

Polymorphism : All methods in java are virtual by default. That means that any method can be overridden when used in inheritance, unless that method is declared as final or static.(Explanation Belongs to Virtual Tables Concept)

Virtual Table / Dispatch Table : An object's dispatch table will contain the addresses of the object's dynamically bound methods. Method calls are performed by fetching the method's address from the object's dispatch table. The dispatch table is the same for all objects belonging to the same class, and is therefore typically shared between them.

public static void main (String[] args) {
      /**
       * Creating the different objects with super class Reference
       */
     Dog obj1 = new Dog();
`         /**
           *  Object of Pet Dog is created with Dog Reference since                
           *  Upcasting is done automatically for us we don't have to worry about it 
           *  
           */
     Dog obj2 = new PetDog();
`         /**
           *  Object of Police Dog is created with Dog Reference since                
           *  Upcasting is done automatically for us we don't have to worry       
           *  about it here even though we are extending PoliceDog with PetDog 
           *  since PetDog is extending Dog Java automatically upcast for us 
           */
      Dog obj3 = new PoliceDog();
}



 obj1.getType();

Prints Normal Dog

  obj2.getType();

Prints Pet Dog

 obj3.getType();

Prints Police Dog

Downcasting need to be done by the programmer manually

When you try to invoke the secretID(); method on obj3 which is PoliceDog object but referenced to Dog which is a super class in the hierarchy it throws error since obj3 don't have access to secretId() method.In order to invoke that method you need to Downcast that obj3 manually to PoliceDog

  ( (PoliceDog)obj3).secretID();

which prints ID

In the similar way to invoke the dogName();method in PetDog class you need to downcast obj2 to PetDog since obj2 is referenced to Dog and don't have access to dogName(); method

  ( (PetDog)obj2).dogName();

Why is that so, that upcasting is automatical, but downcasting must be manual? Well, you see, upcasting can never fail. But if you have a group of different Dogs and want to downcast them all to a to their types, then there's a chance, that some of these Dogs are actually of different types i.e., PetDog, PoliceDog, and process fails, by throwing ClassCastException.

This is the reason you need to downcast your objects manually if you have referenced your objects to the super class type.

Note: Here by referencing means you are not changing the memory address of your ojects when you downcast it it still remains same you are just grouping them to particular type in this case Dog


I know this question asked quite long time ago but for the new users of this question. Please read this article where contains complete description on upcasting, downcasting and use of instanceof operator

  • There's no need to upcast manually, it happens on its own:

    Mammal m = (Mammal)new Cat(); equals to Mammal m = new Cat();

  • But downcasting must always be done manually:

    Cat c1 = new Cat();      
    Animal a = c1;      //automatic upcasting to Animal
    Cat c2 = (Cat) a;    //manual downcasting back to a Cat
    

Why is that so, that upcasting is automatical, but downcasting must be manual? Well, you see, upcasting can never fail. But if you have a group of different Animals and want to downcast them all to a Cat, then there's a chance, that some of these Animals are actually Dogs, and process fails, by throwing ClassCastException. This is where is should introduce an useful feature called "instanceof", which tests if an object is instance of some Class.

 Cat c1 = new Cat();         
    Animal a = c1;       //upcasting to Animal
    if(a instanceof Cat){ // testing if the Animal is a Cat
        System.out.println("It's a Cat! Now i can safely downcast it to a Cat, without a fear of failure.");        
        Cat c2 = (Cat)a;
    }

For more information please read this article


We can create object to Downcasting. In this type also. : calling the base class methods

Animal a=new Dog();
a.callme();
((Dog)a).callme2();

1.- Upcasting.

Doing an upcasting, you define a tag of some type, that points to an object of a subtype (Type and subtype may be called class and subclass, if you feel more comfortable...).

Animal animalCat = new Cat();

What means that such tag, animalCat, will have the functionality (the methods) of type Animal only, because we've declared it as type Animal, not as type Cat.

We are allowed to do that in a "natural/implicit/automatic" way, at compile-time or at a run-time, mainly because Cat inherits some of its functionality from Animal; for example, move(). (At least, cat is an animal, isn't it?)

2.- Downcasting.

But, what would happen if we need to get the functionality of Cat, from our type Animal tag?.

As we have created the animalCat tag pointing to a Cat object, we need a way to call the Cat object methods, from our animalCat tag in a some smart pretty way.

Such procedure is what we call Downcasting, and we can do it only at the run-time.

Time for some code:

public class Animal {
    public String move() {
        return "Going to somewhere";
    }
}

public class Cat extends Animal{
    public String makeNoise() {
        return "Meow!";
    }   
}

public class Test {

    public static void main(String[] args) {
        
    //1.- Upcasting 
    //  __Type_____tag________object
        Animal animalCat = new Cat();
    //Some animal movement
        System.out.println(animalCat.move());
        //prints "Going to somewhere"
        
    //2.- Downcasting   
    //Now you wanna make some Animal noise.
        //First of all: type Animal hasn't any makeNoise() functionality.
        //But Cat can do it!. I wanna be an Animal Cat now!!
        
        //___________________Downcast__tag_____ Cat's method
        String animalNoise = ( (Cat) animalCat ).makeNoise();
        
        System.out.println(animalNoise);
        //Prints "Meow!", as cats usually done.
        
    //3.- An Animal may be a Cat, but a Dog or a Rhinoceros too.
        //All of them have their own noises and own functionalities.
        //Uncomment below and read the error in the console:
        
    //  __Type_____tag________object
        //Cat catAnimal = new Animal();
        
    }

}

Down-casting and up-casting was as follows:
enter image description here

Upcasting: When we want to cast a Sub class to Super class, we use Upcasting(or widening). It happens automatically, no need to do anything explicitly.

Downcasting : When we want to cast a Super class to Sub class, we use Downcasting(or narrowing), and Downcasting is not directly possible in Java, explicitly we have to do.

Dog d = new Dog();
Animal a = (Animal) d; //Explicitly you have done upcasting. Actually no need, we can directly type cast like Animal a = d; compiler now treat Dog as Animal but still it is Dog even after upcasting
d.callme();
a.callme(); // It calls Dog's method even though we use Animal reference.
((Dog) a).callme2(); // Downcasting: Compiler does know Animal it is, In order to use Dog methods, we have to do typecast explicitly.
// Internally if it is not a Dog object it throws ClassCastException

Better try this method for upcasting, it's easy to understand:

/* upcasting problem */
class Animal
{ 
    public void callme()
    {
        System.out.println("In callme of Animal");
    }
}

class Dog extends Animal 
{ 
    public void callme()
    {
        System.out.println("In callme of Dog");
    }

    public void callme2()
    {
        System.out.println("In callme2 of Dog");
    }
}

public class Useanimlas 
{
    public static void main (String [] args) 
    {
        Animal animal = new Animal ();
        Dog dog = new Dog();
        Animal ref;
        ref = animal;
        ref.callme();
        ref = dog;
        ref.callme();
    }
}

upcasting means casting the object to a supertype, while downcasting means casting to a subtype.

In java, upcasting is not necessary as it's done automatically. And it's usually referred as implicit casting. You can specify it to make it clear to others.

Thus, writing

Animal a = (Animal)d;

or

Animal a = d;

leads to exactly the same point and in both cases will be executed the callme() from Dog.

Downcasting is instead necessary because you defined a as object of Animal. Currently you know it's a Dog, but java has no guarantees it's. Actually at runtime it could be different and java will throw a ClassCastException, would that happen. Of course it's not the case of your very sample example. If you wouldn't cast a to Animal, java couldn't even compile the application because Animal doesn't have method callme2().

In your example you cannot reach the code of callme() of Animal from UseAnimlas (because Dog overwrite it) unless the method would be as follow:

class Dog extends Animal 
{ 
    public void callme()
    {
        super.callme();
        System.out.println("In callme of Dog");
    }
    ... 
} 

Parent: Car
Child: Figo
Car c1 = new Figo();

=====
Upcasting:-
Method: Object c1 will refer to Methods of Class (Figo - Method must be overridden) because class "Figo" is specified with "new".
Instance Variable: Object c1 will refer to instance variable of Declaration Class ("Car").

When Declaration class is parent and object is created of child then implicit casting happens which is "Upcasting".

======
Downcasting:-
Figo f1 = (Figo) c1; //
Method: Object f1 will refer to Method of Class (figo) as initial object c1 is created with class "Figo". but once down casting is done, methods which are only present in class "Figo" can also be referred by variable f1.
Instance Variable: Object f1 will not refer to instance variable of Declaration class of object c1 (declaration class for c1 is CAR) but with down casting it will refer to instance variables of class Figo.

======
Use: When Object is of Child Class and declaration class is Parent and Child class wants to access Instance variable of it's own class and not of parent class then it can be done with "Downcasting".


Maybe this table helps. Calling the callme() method of class Parent or class Child. As a principle:

UPCASTING --> Hiding

DOWNCASTING --> Revealing

enter image description here

enter image description here

enter image description here


Examples related to java

Under what circumstances can I call findViewById with an Options Menu / Action Bar item? How much should a function trust another function How to implement a simple scenario the OO way Two constructors How do I get some variable from another class in Java? this in equals method How to split a string in two and store it in a field How to do perspective fixing? String index out of range: 4 My eclipse won't open, i download the bundle pack it keeps saying error log

Examples related to casting

Subtracting 1 day from a timestamp date Cast object to interface in TypeScript TypeScript enum to object array Casting a number to a string in TypeScript Hive cast string to date dd-MM-yyyy Casting int to bool in C/C++ Swift double to string No function matches the given name and argument types C convert floating point to int PostgreSQL : cast string to date DD/MM/YYYY

Examples related to class-variables

What is the difference between up-casting and down-casting with respect to class variable Ruby class instance variable vs. class variable What does @@variable mean in Ruby? Are static class variables possible in Python?

Examples related to downcast

What is the difference between up-casting and down-casting with respect to class variable Convert base class to derived class downcast and upcast Is it possible to assign a base class object to a derived class reference with an explicit typecast?

Examples related to upcasting

What is the difference between up-casting and down-casting with respect to class variable Why do we assign a parent reference to the child object in Java? downcast and upcast