Say we have two classes.
class Animal{/*code*/}
class Cat extends Animal{/*code*/}
From what I've been learned, upcasting and downcasting works like this
Cat c1 = new Cat();
Animal a = c1; //Upcasted to Animal
Cat c2 = (cat) a; //Downcasted back to Cat
But the only problem is, each time you upcast or downcast, you create a new Object. Is there anyway to upcast and downcast an object from Cat to Animal and back to Cat, so that only one object is being casted? For example
Cat c --> Animal c --> Cat c //Upcasted to Animal, and downcasted back to Cat, but done all on one object.
Thanks!
These 3 lines create only one object in heap and 3 references which point to the very same object
Cat c1 = new Cat(); //this is where object is created in heap
Animal a = c1; //Upcasted to Animal, only reference is created not new object
Cat c2 = (cat) a; //Downcasted back to Cat, only reference is created not new object
You can start debugger and check that those references point to the very same object.
Only one object is being created in memory, and there are three references to this one object. Of note is that the reference of type Animal won't have access to anything specific to the Cat type. Read up on polymorphism if you want to know more.
An important thing to note here is that if you change anything in that object it will be reflected by any of the references. This is demonstrated below. Assume there is an abstract Animal class which has a name and appropriate getter & setter.
Note that even though the setName() is called on the cat variable, the name is still changed when calling getName() on animal.
Cat cat = new Cat("foo");
Animal animal = cat;
System.out.println(animal.getName()); // foo
cat.setName("bar");
System.out.println(animal.getName()); // bar <-- The name of animal changed when we changed cat1.
Can someone explain the differences between these three declarations.
Animal var = new Dog()
Dog var = new Dog()
Dog var = new Animal()
The second declaration is most used, but I don't understand what role the left class has vs the right class, or when you use one vs the other.
The assumption is Dog extends Animal.
The "type on the right" (Dog) is the actual type of the instance being created.
It must be a real class (not an interface).
This class defines the "real, implemented behavior" of the new object.
The "type on the left" (Animal) is the type of the variable being used to store the reference to the instance being created.
The "type on the left" must be an ancestor class/interface of the "class on the right" (otherwise you have to do a cast).
Using this variable (without casts), you will only have access to the properties/methods of Animal (no additional properties/methods of Dog), and you may assume that the contract of Animal is implemented, without knowing any of the details, which you would know if the type was Dog.
This is very basic polymorphism, please read a tutorial/book on this to get more insight.
Here is a small example:
Animal a1 = new Animal(); // works
Animal a2 = new Dog(); // works, Dog a subtype of animal
Dog d1 = new Animal(); // does not work, Animal not a subtype of Dog
a1 = a2; // works
d1 = a1; // doesn't work
// If Dog has a function "bark" and Animal has a function "breathe"
a1.breathe(); // works
d1.breathe(); // works
d1.bark(); // works
a1.bark(); // does not compile, Animal not always a Dog
See it like this: All Dogs are Animals, so you can assign a Dog value to an Animal variable. But not all Animals are Dogs, so you can not assign all Animals to a variable of type Dog.
Dog is a specific animal. Therefore you can call Dog animal.
Of course a dog is a dog.
An animal is probably not a dog, it can be a cat, a mouse etc. Therefore you can't use this way.
Let me explain:
package a.b.c.d;
public interface ObjA extends ObjFirst ...
then
package e.f.g.h;
public interface ObjB extends a.b.c.d.ObjA ...
I have a method from package a.b.c.d that return me an ObjA and when I try to implicitly cast it to ObjB it return the error:
Type mismatch: cannot convert from a.b.c.d.ObjA to e.f.g.h.ObjB
where am I wrong?
What you are trying to do is called "downcast", and the compiler won't let you do it implicitly. That's because the compiler does not know whether an instance of ObjA is an instance of ObjB too.
Let's take this as example:
class Animal {
//...
}
class Dog extends Animal {
//...
}
class Cat extends Animal {
//...
}
Dog is-an Animal, Cat is-an Animal.
So you will be able to do:
Cat cat = new Cat();
Animal animal = c;
But you won't be able to do:
Animal animal = new Animal();
Cat cat = animal;
In fact, try to think about it. If I tell you "I have an animal", how can you know for sure it is a cat?
If you want to downcast you have to do it explicitly:
/*
* Here myAnimal is an Animal. In order to cast,
* I **must** be sure that myAnimal is a cat.
*/
Cat cat = (Cat) myAnimal;
In order to be really sure that myAnimal is a Cat:
if(myAnimal instanceof Cat) {
Cat cat = (Cat) myAnimal;
// do whatever you need to do with that cat object
}
Since ObjB is a sub-interface of ObjA, you can't pass ObjA instances to methods/variables that expect ObjB instances without an explicit cast, since not all ObjA instances are ObjB instances (you might have an ObjC interface that extends ObjA and does not implement ObjB).
You should check the type of the variable (using var instanceof ObjB) and then explicitly cast is to ObjB (using (ObjB) var).
ObjB know about ObjA and ObjFirst
ObjA know about ObjFirst
But here we are trying to cast ObjA to ObjB where it was not aware of.
we can check this simply by using "instanceof" operator
ObjB instanceof ObjA is true
ObjA instanceof ObjB returns false
You need to actively cast it, as down-casting is not supported. By trying to down-cast, you are implicitly expecting the system to try and find the interface in something which could be best described as an inheritance-tree. Problem is, that if down-casting would be supported, then whenever you are using an object of some arbitrary type, the system should always try to find the sub-class/sub-interface matching it. It can be supported or not. In our case it is not supported and I believe that is a very good thing. What if no such subclass, subinterface exists? It would be a runtime-exception, possibly when the code is already released.
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();
}
}
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.
In your case, a cast from a 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.
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.
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.
To call a superclass's method you can do super.method() or by performing the upcast.
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 ClassCastExceptions:
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;
}
Downcasts can be expressed more succinctly starting from Java 16, which introduced pattern matching for instanceof:
Animal animal = getAnimal(); // Maybe a Dog? Maybe a Cat? Maybe an Animal?
if (animal instanceof Dog castedDog) {
// now castedDog is available here as in the example above
}
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
Autoboxing-vs-Casting
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
Dog - This is the super Class.
Pet Dog - Pet Dog extends Dog.
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
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:
UPCASTING --> Hiding
DOWNCASTING --> Revealing
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();
}
}
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");
}
...
}
We can create object to Downcasting. In this type also. : calling the base class methods
Animal a=new Dog();
a.callme();
((Dog)a).callme2();
I have a stupid Java question, here is a scenario
Class A {}
Class AA extends A{}
AA aa = new AA()
A a = new A()
when I do
aa = (AA) a;
I got some error like Exception in thread "main" java.lang.ClassCastException: A cannot be cast to AA
where is the problem?
Here's your inheritance hierarchy
Object
|
A <--------- your object
|
AA
The variable a is referencing an object of type A, but you are trying to cast it to an AA. This isn't possible since an A is not an AA.
An AA is an A, so you could have done
A a = new AA();
AA a = (AA) a;
but you've done the opposite.
you can cast sub class instance to superclass but you can not cast super class instance to subclass.
A variable referencing an object can be the same type as that object, or it can be any supertype of that object
SubType sub = new SuperType();
...will fail to compile, because "new SuperType()" returns a reference of type SuperType, and the compiler knows that a SuperType is NOT a Subtype.
class Animal { }
class Dog extends Animal { }
class DogTest {
public static void main(String [] args) {
Animal animal = new Animal();
Dog d = (Dog) animal; // compiles but fails later
}
}
It can be maddening! This code compiles! When we try to run it, we'll get an
exception something like this:
java.lang.ClassCastException
Why can't we trust the compiler to help us out here? Can't it see that animal
is of type Animal?
All the compiler can do is verify that the two types are in the
same inheritance tree, so that depending on whatever code might have come before
the downcast, it's possible that animal is of type Dog. The compiler must allow
things that might possibly work at runtime.
However, if the compiler knows with
certainty that the cast could not possibly work, compilation will fail.
The following
replacement code block will NOT compile:
Animal animal = new Animal();
Dog d = (Dog) animal;
String s = (String) animal; // animal can't EVER be a String
In this case, you'll get an error something like this:
inconvertible types