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

Multi tool use
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();
}
}
Dog
Animal
callme
Animal
Dog
callme2
Dog
a
Dog
What is the output of your code?
– Malwinder Singh
Apr 28 '15 at 5:25
The interesting thing is, that d.callme returns 'In callme of Dog' although d was casted to animal!!
– Chris311
Jan 11 '16 at 16:40
@Chris311 both 'd' and 'a' point to the same object ... which is a Dog, but 'a' has access to only Dog specific methods when it is downcast at runtime. Infact : Animal a = (Animal)d; is unnecessary, you only need Animal a = d; as you're upcasting.
– Mark Keen
Jan 13 '16 at 2:18
9 Answers
9
Upcasting is casting to a supertype, while downcasting is casting to a subtype. Upcasting is always allowed, but downcasting involves a type check and can throw a ClassCastException
.
ClassCastException
In your case, a cast from from Dog
to an Animal
is an upcast, because a Dog
is-a Animal
. In general, you can upcast whenever there is an is-a relationship between two classes.
Dog
Animal
Dog
Animal
Downcasting would be something like this:
Animal animal = new Dog();
Dog castedDog = (Dog) animal;
Basically what you're doing is telling the compiler that you know what the runtime type of the object really is. The compiler will allow the conversion, but will still insert a runtime sanity check to make sure that the conversion makes sense. In this case, the cast is possible because at runtime animal
is actually a Dog
even though the static type of animal
is Animal
.
animal
Dog
animal
Animal
However, if you were to do this:
Animal animal = new Animal();
Dog notADog = (Dog) animal;
You'd get a ClassCastException
. The reason why is because animal
's runtime type is Animal
, and so when you tell the runtime to perform the cast it sees that animal
isn't really a Dog
and so throws a ClassCastException
.
ClassCastException
animal
Animal
animal
Dog
ClassCastException
To call a superclass's method you can do super.method()
or by performing the upcast.
super.method()
To call a subclass's method you have to do a downcast. As shown above, you normally risk a ClassCastException
by doing this; however, you can use the instanceof
operator to check the runtime type of the object before performing the cast, which allows you to prevent ClassCastException
s:
ClassCastException
instanceof
ClassCastException
Animal animal = getAnimal(); // Maybe a Dog? Maybe a Cat? Maybe an Animal?
if (animal instanceof Dog) {
// Guaranteed to succeed, barring classloader shenanigans
Dog castedDog = (Dog) animal;
}
Does proper downcasting ensures no
ClassCastException
or not? Like in the first case?– Malwinder Singh
Apr 28 '15 at 5:16
ClassCastException
@M.S. What do you mean by "proper"?
– awksp
Apr 29 '15 at 18:21
instanceOf operator can be used to check whether class can be cast or not to reduce the risk of ClassCastException.
– Vaibhav Jain
Aug 21 '16 at 17:28
@awksp This is an excellent and articulate answer. Pretty much sums up everything I need to know about Casting.
– Gautham Honnavara
Nov 16 '16 at 20:14
surely you haven't made classes where animal is an instance of dog have you? so why are you even checking for it?
– barlop
Aug 9 '17 at 7:26
Down-casting and up-casting was as follows:
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
So, there is no such a way of doing upcasting to call the method's parent?
– karlihnos
Jul 5 '17 at 15:19
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.
getType();
Assume you have three dogs
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
Normal Dog
obj2.getType();
Prints Pet Dog
Pet Dog
obj3.getType();
Prints Police Dog
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
secretID();
obj3
PoliceDog object
Dog
obj3
secretId()
PoliceDog
( (PoliceDog)obj3).secretID();
which prints ID
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
dogName();
PetDog
obj2
PetDog
Dog
dogName();
( (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
.
PetDog
PoliceDog
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
Dog
'Polymorphism uses automatic downcast during method calls.' No it doesn't. The mechanism used isn't specified, but the most usual mechanism -a vtable - does no such thing. Look in the object code. No downcast.
– EJP
Sep 27 '15 at 23:32
Why not? This is what happens right can you give a example where it will not work ?
– Nagarjuna Yelisetty
Sep 27 '15 at 23:44
Why not? This is what happens right .. can you give a example where the statement 'Polymorphism uses automatic downcast during method calls.' will fail or will not hold true ?
– Nagarjuna Yelisetty
Sep 27 '15 at 23:50
'As per my knowledge my statements are true and it holds in every case' is not a proof. It is a mere assertion. I am asking you to prove your statements. You're not doing so. In effect you're only repeating yourself. And I have already provided several refutations. I've also provided a decision procedure. If you can find a downcast in the object code for a method call, you're right and I'm wrong. This is how science is done. Do it. And claiming that I am 'boldly depending on the documentation' is a blatant misrepresentation. Don't do that.
– EJP
Sep 28 '15 at 0:10
Editing the answer !!
– Nagarjuna Yelisetty
Sep 28 '15 at 0:12
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();
Mammal m = (Mammal)new Cat();
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
good point : Mammal m = (Mammal)new Cat(); equals to Mammal m = new Cat();
– Catbuilts
Dec 27 '16 at 15:44
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();
}
}
Maybe this table helps.
Calling the callme()
method of class Parent
or class Child
.
As a principle:
callme()
Parent
Child
UPCASTING --> Hiding
DOWNCASTING --> Revealing
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".
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
.
callme()
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()
.
a
Dog
ClassCastException
a
Animal
Animal
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:
callme()
Animal
UseAnimlas
Dog
class Dog extends Animal
{
public void callme()
{
super.callme();
System.out.println("In callme of Dog");
}
...
}
We can create object to Downcasting. In this type also. : calling the base class methods
Animal a=new Dog();
a.callme();
((Dog)a).callme2();
Thank you for your interest in this question.
Because it has attracted low-quality or spam answers that had to be removed, posting an answer now requires 10 reputation on this site (the association bonus does not count).
Would you like to answer one of these unanswered questions instead?
A
Dog
is anAnimal
. Most of the times upcasting is unnecessary unless you want to use a certain overloaded method.callme
exists in bothAnimal
andDog
.callme2
only exists inDog
, which you casta
toDog
to make it work.– Brian
May 1 '14 at 19:09