JavaRush /Java Blog /Random EN /Extension and narrowing of reference types

Extension and narrowing of reference types

Published in the Random EN group
Hello! In one of the previous lectures, we discussed casting primitive types. Let's briefly recall what was discussed. Extension and contraction of reference types - 1We represented primitive types (in this case, numeric ones) in the form of matryoshka dolls according to the amount of memory they occupy. As you remember, putting a smaller nesting doll into a larger one will be easy both in real life and in Java programming.
public class Main {
   public static void main(String[] args) {
        short smallNumber = 100;
        int bigNumber =  smallNumber;
        System.out.println(bigNumber);
   }
}
This is an example of automatic conversion, or expansion . It happens on its own, so no additional code needs to be written. After all, we're not doing anything out of the ordinary: we're just putting a smaller nesting doll into a larger nesting doll. Another thing is if we try to do the opposite and put a large nesting doll in a smaller one. In life, this cannot be done, but in programming it is possible. But there is one caveat. If we try to put a value intin a variable short, we won't be able to do it that easily. After all, only 16 bits of information will fit in a variable short, and the value inttakes 32 bits! As a result, the transmitted value will be distorted. The compiler will give us an error (" dude, you're doing something fishy!”), but if we explicitly specify what type we cast our value to, it will still perform such an operation.
public class Main {

   public static void main(String[] args) {

       int bigNumber = 10000000;

       bigNumber = (short) bigNumber;

       System.out.println(bigNumber);

   }

}
In the example above, we did just that. The operation was completed, but since shortonly 16 bits out of 32 fit in the variable, the final value was distorted, and as a result we got the number -27008 . Such an operation is called an explicit transformation, or narrowing .

Reference Type Extension and Narrowing Examples

Now we will talk about the same operations, but not with primitive types, but with objects and reference variables ! How does it work in Java? Actually, it's quite simple. There are objects that are not related to each other. It would be logical to assume that they cannot be converted to each other either explicitly or automatically:
public class Cat {
}

public class Dog {
}

public class Main {

   public static void main(String[] args) {

       Cat cat = new Dog();//error!

   }

}
Here, of course, we will get an error. The classes Catare Dognot related to each other, and we did not write a "transformer" of one in the other. It is logical that we will not be able to do this: the compiler has no idea how to convert these objects to each other. Another thing is if the objects are interconnected! How? First of all, with the help of inheritance. Let's try to create a small class system with inheritance. We will have a general class denoting animals:
public class Animal {

   public void introduce() {

       System.out.println("i'm Animal");
   }
}
Animals, as you know, are domestic and wild:
public class WildAnimal extends Animal {

   public void introduce() {

       System.out.println("i'm WildAnimal");
   }
}

public class Pet extends Animal {

   public void introduce() {

       System.out.println("i'm Pet");
   }
}
For example, let's take dogs - a domestic dog and a coyote:
public class Dog extends Pet {

   public void introduce() {

       System.out.println("i'm Dog");
   }
}





public class Coyote extends WildAnimal {

   public void introduce() {

       System.out.println("i'm Coyote");
   }
}
Our classes are specially the most primitive, so that it is easier to perceive them. We don’t really need fields here, and one method is enough. Let's try to execute the following code:
public class Main {

   public static void main(String[] args) {

       Animal animal = new Pet();
       animal.introduce();
   }
}
What do you think will be printed to the console? introduceWill a class Petor class method work Animal? Try to justify your answer before continuing reading. And here is the result! i'm Pet Why is the answer like this? Everything is simple. We have a parent variable and a child object. By writing:
Animal animal = new Pet();
we have extended the reference typePet and written its object into a variable Animal. As with primitives, extension of reference types in Java is done automatically. You don't need to write additional code for this. Now we have a child object attached to the parent reference, and as a result, we see that the method call is made on the child class. If you still don't fully understand why this code works, rewrite it in plain language:
Животное животное = new ДомашнееЖивотное();
There is no problem with this, right? Imagine that this is real life, and the link in this case is a simple paper tag with the inscription "Animal". If you take such a piece of paper and attach it to the collar of any pet, everything will be all right. Any pet is still an animal! The reverse process, that is, moving down the inheritance tree to the heirs, is a narrowing:
public class Main {

   public static void main(String[] args) {

       WildAnimal wildAnimal = new Coyote();

       Coyote coyote = (Coyote) wildAnimal;

       coyote.introduce();
   }
}
As you can see, here we explicitly indicate to which class we want to cast our object. Previously, we had a variable WildAnimal, and now Coyotewe have a variable that goes down the inheritance tree below. It is logical that the compiler will not miss such an operation without an explicit indication, but if you specify the type in brackets, everything will work. Extension and contraction of reference types - 2 Let's look at another, more interesting example:
public class Main {

   public static void main(String[] args) {

       Pet pet = new Animal();//error!
   }
}
The compiler throws an error! What is the reason? In that you are trying to assign a parent object to a child variable. In other words, you want to do something like this:
ДомашнееЖивотное домашнееЖивотное = new Животное();
But maybe if we explicitly specify the type to which we are trying to cast, we will succeed? With numbers like it turned out, let's try! :)
public class Main {

   public static void main(String[] args) {

       Pet pet = (Pet) new Animal();
   }
}
Exception in thread "main" java.lang.ClassCastException: Animal cannot be cast to Pet The compiler did not swear this time, however, as a result, we got an exception. We already know the reason: we are trying to assign a parent object to a child variable. And why, in fact, can not do this? Because not all Animals are Pets. You have created an object Animaland are trying to assign it to a variable Pet. But, for example, the coyote is also Animal, but it is not Pet, a pet. In other words, when you write:
Pet pet = (Pet) new Animal();
new Animal()Any animal can be on the spot , and not necessarily a domestic one! Naturally, your variable Pet petis only suitable for storing pets (and their descendants), and not for everyone. Therefore, for such cases, a special exception was created in Java - ClassCastException, error when casting classes. Let's talk again to make it clearer. A parent variable (reference) can point to an object of a child class:
public class Main {

   public static void main(String[] args) {

       Pet pet =  new Pet();
       Animal animal = pet;

       Pet pet2 = (Pet) animal;
       pet2.introduce();
   }
}
For example, here we have no problems. We have an object Petto which the reference points Pet. Then a new link began to point to the same object Animal. Then we do the conversion animalto Pet. Why did we do it, by the way? We got an exception last time! Because this time our original object is Pet pet!
Pet pet =  new Pet();
And in the previous example, it was an object Animal:
Pet pet = (Pet) new Animal();
A descendant variable cannot be assigned an ancestor object. On the contrary, you can do it.
Comments
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION