JavaRush /Blog Java /Random-ES /Expansión y contracción de tipos de referencia.

Expansión y contracción de tipos de referencia.

Publicado en el grupo Random-ES
¡Hola! En una de las conferencias anteriores, discutimos la conversión de tipos primitivos. Recordemos brevemente de qué estábamos hablando. Expansión y contracción de tipos de referencia - 1Representamos los tipos primitivos (en este caso, numéricos) como muñecos nido según la cantidad de memoria que ocupan. Como recordarás, colocar una muñeca nido más pequeña en una más grande será sencillo tanto en la vida real como en la programación Java.
public class Main {
   public static void main(String[] args) {
        short smallNumber = 100;
        int bigNumber =  smallNumber;
        System.out.println(bigNumber);
   }
}
Este es un ejemplo de conversión automática o extensión . Sucede por sí solo, por lo que no es necesario escribir código adicional. Al final, no estamos haciendo nada inusual: simplemente estamos colocando una muñeca nido más pequeña dentro de una muñeca nido más grande. Otra cosa es si intentamos hacer lo contrario y meter una matrioska grande en una más pequeña. Esto no se puede hacer en la vida, pero en la programación se puede hacer. Pero hay una advertencia. Si intentamos poner un valor inten una variable short, no funcionará tan fácilmente. Después de todo, sólo 16 bits de información pueden caber en una variable short, ¡pero el valor intrequiere 32 bits! Como resultado, el valor transmitido se distorsionará. El compilador nos dará un error (“ ¡amigo, estás haciendo algo sospechoso! ”), pero si especificamos explícitamente a qué tipo estamos emitiendo nuestro valor, igualmente realizará dicha operación.
public class Main {

   public static void main(String[] args) {

       int bigNumber = 10000000;

       bigNumber = (short) bigNumber;

       System.out.println(bigNumber);

   }

}
En el ejemplo anterior, hicimos precisamente eso. La operación se completó, pero como shortsolo 16 de los 32 bits caben en la variable, el valor final se distorsionó y como resultado obtuvimos el número -27008 . Esta operación se llama conversión explícita o reducción .

Ejemplos de extensión y contracción de tipos de referencia.

Ahora hablaremos de las mismas operaciones, pero aplicables no a tipos primitivos, sino a objetos y variables de referencia . ¿Cómo funciona esto en Java? En realidad, bastante simple. Hay objetos que no están relacionados entre sí. Sería lógico suponer que no se pueden convertir entre sí ni explícita ni automáticamente:
public class Cat {
}

public class Dog {
}

public class Main {

   public static void main(String[] args) {

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

   }

}
Aquí, por supuesto, obtendremos un error. Las clases no Catestán Dogrelacionadas entre sí y no hemos escrito un “conversor” de una a otra. Es lógico que no podamos hacer esto: el compilador no tiene idea de cómo convertir estos objetos entre sí. ¡Otra cuestión es si los objetos están conectados entre sí! ¿Cómo? En primer lugar, utilizando la herencia. Intentemos crear un sistema de clases pequeño con herencia. Tendremos una clase general representando animales:
public class Animal {

   public void introduce() {

       System.out.println("i'm Animal");
   }
}
Los animales, como sabéis, son domésticos y salvajes:
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");
   }
}
Por ejemplo, tomemos perros: un perro doméstico y un 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");
   }
}
Nuestras clases son deliberadamente las más primitivas para que sean más fáciles de percibir. Realmente no necesitamos campos aquí y un método es suficiente. Intentemos ejecutar el siguiente código:
public class Main {

   public static void main(String[] args) {

       Animal animal = new Pet();
       animal.introduce();
   }
}
¿Qué crees que se enviará a la consola? introduce¿Funcionará la clase Peto el método de clase Animal? Intenta justificar tu respuesta antes de continuar leyendo. ¡Y aqui esta el resultado! Soy mascota ¿Por qué la respuesta fue así? Es sencillo. Tenemos una variable principal y un objeto secundario. Al escribir:
Animal animal = new Pet();
Hemos extendido un tipo de referenciaPet y almacenado su objeto en una variable Animal. Al igual que con los tipos primitivos, la extensión de los tipos de referencia en Java se realiza automáticamente. No es necesario escribir código adicional para esto. Ahora tenemos un objeto hijo adjunto a la referencia principal y, como resultado, vemos que el método se llama en la clase hija. Si aún no comprende completamente por qué funciona este código, vuelva a escribirlo en un lenguaje sencillo:
Животное животное = new ДомашнееЖивотное();
No hay ningún problema con eso, ¿verdad? Imagínese que esto es la vida real y que el enlace en este caso es una simple etiqueta de papel que dice "Animal". Si tomas ese trozo de papel y lo colocas en el collar de cualquier mascota, todo estará bien. ¡Cualquier mascota sigue siendo un animal! El proceso inverso, es decir, descender en el árbol de herencia hasta los herederos, es una reducción:
public class Main {

   public static void main(String[] args) {

       WildAnimal wildAnimal = new Coyote();

       Coyote coyote = (Coyote) wildAnimal;

       coyote.introduce();
   }
}
Como puede ver, aquí indicamos explícitamente a qué clase queremos convertir nuestro objeto. Anteriormente teníamos una variable WildAnimal, y ahora Coyote, que desciende en el árbol de herencia. Es lógico que el compilador no omita dicha operación sin una indicación explícita, pero si especifica el tipo entre paréntesis, todo funcionará. Expansión y contracción de tipos de referencia - 2 Veamos otro ejemplo, más interesante:
public class Main {

   public static void main(String[] args) {

       Pet pet = new Animal();//¡error!
   }
}
¡El compilador arroja un error! ¿Cuál es la razón? El hecho es que está intentando asignar un objeto principal a una variable secundaria. En otras palabras, quieres hacer esto:
ДомашнееЖивотное домашнееЖивотное = new Животное();
Pero tal vez si indicamos explícitamente el tipo al que estamos intentando convertir, ¿tendremos éxito? Los números parecen funcionar, ¡probemos! :)
public class Main {

   public static void main(String[] args) {

       Pet pet = (Pet) new Animal();
   }
}
Excepción en el hilo "principal" java.lang.ClassCastException: ¡El animal no puede convertirse en Error de mascota! El compilador no se quejó esta vez, pero como resultado recibimos una excepción. Ya sabemos el motivo: estamos intentando asignar un objeto padre a una variable hija. ¿Por qué, de hecho, no se puede hacer esto? Porque no todos los animales son mascotas. Creaste un objeto Animaly estás intentando asignarlo a una variable Pet. Pero, por ejemplo, un coyote también es Animal, pero no lo es Pet, un animal doméstico. En otras palabras, cuando escribes:
Pet pet = (Pet) new Animal();
new Animal()Cualquier animal puede estar allí , ¡y no tiene por qué ser doméstico! Naturalmente, su variable Pet petsólo es adecuada para almacenar mascotas (y sus descendientes), y no para todos. Por lo tanto, para tales casos, se creó una excepción especial en Java: ClassCastExceptionun error al transmitir clases. Digámoslo de nuevo para que quede más claro. Una variable principal (referencia) puede apuntar a un objeto de una clase descendiente:
public class Main {

   public static void main(String[] args) {

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

       Pet pet2 = (Pet) animal;
       pet2.introduce();
   }
}
Por ejemplo, aquí no tendremos ningún problema. Tenemos un objeto Petal que apunta un enlace Pet. Entonces un nuevo enlace empezó a apuntar al mismo objeto Animal. Después de lo cual hacemos la conversión animala Pet. Por cierto, ¿por qué hicimos esto? ¡La última vez tuvimos una excepción! ¡ Porque esta vez nuestro objeto original es Pet pet!
Pet pet =  new Pet();
Y en el ejemplo anterior era un objeto Animal:
Pet pet = (Pet) new Animal();
A una variable descendiente no se le puede asignar un objeto ancestro. Al contrario, puedes hacerlo.
Comentarios
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION