JavaRush /Java Blog /Random EN /Expansion and contraction of reference types

Expansion and contraction of reference types

Published in the Random EN group
Hello! In one of the previous lectures, we discussed casting primitive types. Let's briefly remember what we were talking about. Expansion and contraction of reference types - 1We represented primitive types (in this case, numeric) as nesting dolls according to the amount of memory they occupy. As you remember, placing a smaller nesting doll into a larger one will be simple 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 extension . It happens on its own, so there is no need to write additional code. In the end, we are not doing anything unusual: we are simply putting a smaller nesting doll into a larger nesting doll. It’s another matter if we try to do the opposite and put a large matryoshka doll into a smaller one. This cannot be done in life, but in programming it can be done. But there is one caveat. If we try to put a value intinto a variable short, it won't work out that easily. After all, only 16 bits of information can fit into a variable short, but 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 suspicious! ”), but if we explicitly specify what type we are casting 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 of the 32 bits fit into the variable, the final value was distorted, and as a result we received the number -27008 . This operation is called explicit conversion, or narrowing .

Examples of extension and contraction of reference types

Now we will talk about the same operations, but applicable not to primitive types, but to objects and reference variables ! How does this work in Java? Quite simple actually. 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 we will, of course, get an error. The classes Catare Dognot related to each other, and we have not written a “converter” from one to another. It’s logical that we won’t be able to do this: the compiler has no idea how to convert these objects between each other. It’s another matter if the objects are connected to each other! How? First of all, using inheritance. Let's try to create a small class system with inheritance. We will have a general class representing 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 deliberately the most primitive to make them easier to perceive. We don’t really need fields here, and one method is enough. Let's try to run the following code:
public class Main {

   public static void main(String[] args) {

       Animal animal = new Pet();
       animal.introduce();
   }
}
What do you think will be output to the console? introduceWill the class Petor class method work Animal? Try to justify your answer before continuing reading. And here is the result! i'm Pet Why did the answer turn out this way? It's simple. We have a parent variable and a child object. By writing:
Animal animal = new Pet();
We have extended a reference typePet and stored its object in a variable Animal. As with primitive types, extension of reference types in Java is done automatically. There is no 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 is called on the child class. If you still don't fully understand why this code works, rewrite it in simple language:
Животное животное = new ДомашнееЖивотное();
There's no problem with that, right? Imagine this is real life, and the link in this case is a simple paper tag that says “Animal.” If you take such a piece of paper and attach it to the collar of any pet, everything will be fine. 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 which class we want to cast our object to. Previously we had a variable WildAnimal, and now Coyote, which goes down the inheritance tree. It is logical that the compiler will not skip such an operation without an explicit indication, but if you specify the type in parentheses, everything will work. Expansion and contraction of reference types - 2 Let's look at another example, more interesting:
public class Main {

   public static void main(String[] args) {

       Pet pet = new Animal();//error!
   }
}
The compiler throws an error! What is the reason? The fact is that you are trying to assign a parent object to a child variable. In other words, you want to do this:
ДомашнееЖивотное домашнееЖивотное = new Животное();
But maybe if we explicitly indicate the type we are trying to cast to, we will succeed? The numbers seem to work, let's try it! :)
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 Error! The compiler did not complain this time, but as a result we received an exception. We already know the reason: we are trying to assign a parent object to a child variable. Why, in fact, can’t this be done? Because not all Animals are Pets. You created an object Animaland are trying to assign it to a variable Pet. But, for example, a coyote is also Animal, but it is not Pet, a domestic animal. In other words, when you write:
Pet pet = (Pet) new Animal();
new Animal()Any animal can be there , and it doesn’t have to be domestic! 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 - ClassCastExceptionan error when casting classes. Let's say it again to make it clearer. A parent variable (reference) can point to an object of a descendant 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, we won’t have any problems here. We have an object Petthat is pointed to by a link Pet. Then a new link began to point to the same object Animal. After which we do the conversion animalto Pet. Why did we do this, by the way? Last time we got an exception! 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