Good day, Javarashovets. I started getting questions about reference type casting in Java. In order not to retell the same thing every time, I decided to write a small article.
First, let's look at what type casting is.
Type casting (type conversion) is the conversion of a value of a variable of one type to a value of another type. Let's look at an example of what it is and what it is eaten with. We have some class hierarchy ( see Figure 1 ). Here you can see all the classes of the hierarchy, who inherits whom and the methods of each class. There are expanding and contracting casts. We see that the classCat
is an inheritor of the class Pet
. Pet
, in turn, is a descendant of the class Animal
. When we write:
Animal animalCat = new Cat();
Animal animalDog = new YorkshireTerrier();
This is a widening (or implicit) cast. We have extended links animalCat
and animalDog
. They refer to objects Cat
and Dog
. With such a cast, we cannot animalCat/animalDog
call methods through the link that are in Cat/Dog
but which are not in Animal
. A narrowing cast (or explicit cast) happens in the opposite direction:
Animal animalCat = new Cat();
Animal animalDog = new YorkshireTerrier();
Cat cat =(Cat)animalCat;
YorkshireTerrier dog = (YorkshireTerrier) animalDog;
We explicitly indicated to what type we want to cast this object. BUT, BE CAREFUL!!! If you do like this:
Animal animalCat = new Cat();
YorkshireTerrier dog = (YorkshireTerrier) animalCat;
the compiler will skip this code. But RunTime
it will throw you:
Exception in thread "main" java.lang.ClassCastException: Animals.Cat cannot be cast to Animals.YorkshireTerrier
RunTime
sees that Cat
there are YorkshireTerrier
two different classes. To avoid ClassCastException when narrowing, use instanceof
.
Animal animalCat = new Cat();
if (animalCat instanceof YorkshireTerrier)
{
YorkshireTerrier dog = (YorkshireTerrier) animalCat;
}
If animalCat
is YorkshireTerrier
, then the assignment will occur, if not, nothing will happen.
And now why is this needed if we lose methods and can get such errors
Consider the code that I made according to the diagram in Fig. 1 . ClassAnimal
public abstract class Animal
{
String name;
int age;
String nameOfClass = getClass().getSimpleName();
public void eat(){
System.out.println(nameOfClass + ": Omnomnom");
}
public void sleep(){
System.out.println(nameOfClass + ": Z-z-z-z");
}
}
The class WildAnimal
that inherits fromAnimal
public abstract class WildAnimal extends Animal
{
public void steelChicken()
{
System.out.println(nameOfClass+": Muhaha,I stole a chicken!");
}
}
The class Pet
that inherits fromAnimal
public abstract class Pet extends Animal
{
public void peeInTray(){
System.out.println(nameOfClass + ": Master, I peed");
}
}
The class Fox
that inherits fromWildAnimal
public class Fox extends WildAnimal
{
public void eatColobok(){
System.out.println(nameOfClass + ": I will eat you, Colobok");
}
}
The class Wolf
that inherits fromWildAnimal
public class Wolf extends WildAnimal
{
public void hawlAtTheMoon(){
System.out.println(nameOfClass + ": Ouuuuu!!!Ouuuu!!!");
}
}
The class Cat
that inherits fromPet
public class Cat extends Pet
{
public void sleepOnKeyboard(){
System.out.println(nameOfClass + ": Master, stop working!!I wanna sleep on your keyboard");
}
}
The class YorkshireTerrier
that inherits fromPet
public class YorkshireTerrier extends Pet
{
public void bark(){
System.out.println(nameOfClass + ": Meow!!! Meow!!!");
}
}
Imagine the situation. We need to collect all the animals in one list, feed them and then put them to bed. This is easy to do if we create ArrayList
animals ( Animal
). And then for each animal we call the appropriate methods:
public class ZOO
{
public static void main(String[] args)
{
List<Animal> allAnimals = new ArrayList<>();
allAnimals.add(new Cat());
allAnimals.add(new Wolf());
allAnimals.add(new Fox());
allAnimals.add(new YorkshireTerrier());
for (Animal animal : allAnimals)
{
animal.eat();
animal.sleep();
}
}
}
I can't animal
call a method bark()
or sleepOnKeyboard()
. Because allAnimals
the cat, wolf, yorick and fox are stored in the sheet, but they are reduced to Animal
. And they only have methods that are in Animal
. This is very good, because if we could call all the methods, then why do we need a wolf that sleeps on the keyboard, or a yorick that steals chickens? Thank you for your attention. I hope this article will be useful for you. Criticism and comments are welcome)