CodeGym/Blog Java/Random-ES/Ensanchamiento y Estrechamiento de tipos primitivos
Autor
Aditi Nawghare
Software Engineer at Siemens

Ensanchamiento y Estrechamiento de tipos primitivos

Publicado en el grupo Random-ES
¡Hola! A medida que avanzaba en CodeGym, se encontró con tipos primitivos muchas veces. Aquí hay una breve lista de lo que sabemos sobre ellos:
  1. No son objetos y representan un valor almacenado en la memoria.
  2. Hay varios tipos
    • Números enteros: byte , corto , int , largo
    • Números de coma flotante (fraccionales): float y double
    • Valores lógicos: booleano
    • Valores simbólicos (para representar letras y números): char
  3. Cada tipo tiene su propio rango de valores:

tipo primitivo Tamaño en memoria Rango de valores
byte 8 bits -128 a 127
corto 16 bits -32768 a 32767
carbonizarse 16 bits 0 a 65536
En t 32 bits -2147483648 al 2147483647
largo 64 bits -9223372036854775808 al 9223372036854775807
flotar 32 bits (2 elevado a -149) a ((2 - (2 elevado a -23)) * 2 elevado a 127)
doble 64 bits (-2 elevado a 63) a ((2 elevado a 63) - 1)
booleano 8 (cuando se usa en matrices), 32 (si no se usa en matrices) verdadero o falso
Pero además de tener diferentes valores, también difieren en cuánto espacio ocupan en la memoria. Un int toma más de un byte. Y un largo es más grande que un corto. La cantidad de memoria que ocupan los primitivos se puede comparar con las muñecas rusas que anidan: Ensanchamiento y estrechamiento de tipos primitivos - 2 cada muñeca que anida tiene espacio disponible en su interior. Cuanto más grande es la muñeca de anidación, más espacio hay. Una muñeca de anidación grande ( larga ) se acomodará fácilmente a una int más pequeña . Se ajusta fácilmente y no necesitas hacer nada más. En Java, cuando se trabaja con primitivas, esto se denomina conversión implícita. O dicho de otra manera, se llama ensanchamiento.

Ampliación en Java

Aquí hay un ejemplo simple de una conversión de ampliación:
public class Main {

   public static void main(String[] args) {

       int bigNumber = 10000000;

       byte littleNumber = 16;

       bigNumber = littleNumber;
       System.out.println(bigNumber);
   }
}
Aquí asignamos un valor de byte a una variable int . La asignación tiene éxito sin ningún problema: el valor almacenado en un byte ocupa menos memoria de lo que puede acomodar un int . La pequeña muñeca de anidación (valor de byte) cabe fácilmente dentro de la muñeca de anidación grande ( variable int ). Es un asunto diferente si intenta hacer lo contrario, es decir, poner un valor grande en una variable cuyo rango no puede acomodar un tipo de datos tan grande. Con muñecas de anidación reales, el número simplemente no encajaría. Con Java, puede, pero con matices. Intentemos poner un int en una variable corta :
public static void main(String[] args) {

   int bigNumber = 10000000;

   short littleNumber = 1000;

   littleNumber = bigNumber;// Error!
   System.out.println(bigNumber);
}
¡Error! El compilador entiende que está tratando de hacer algo anormal al empujar una muñeca de anidamiento grande ( int ) dentro de una pequeña ( short ). En este caso, el error de compilación es una advertencia del compilador: "Oye, ¿estás absolutamente seguro de que quieres hacer esto?" Si está seguro, le dice al compilador: "Todo está bien. ¡Sé lo que estoy haciendo!" Este proceso se denomina conversión de tipo explícita o estrechamiento.

Estrechamiento en Java

Para realizar una conversión de restricción, debe indicar explícitamente el tipo al que desea convertir su valor. En otras palabras, debe responder la pregunta del compilador: "Bueno, ¿en cuál de estos pequeños muñecos de anidación quiere poner este gran muñeco de anidación?" En nuestro caso, se ve así:
public static void main(String[] args) {

   int bigNumber = 10000000;

   short littleNumber = 1000;

   littleNumber = (short) bigNumber;
   System.out.println(littleNumber);
}
Indicamos explícitamente que queremos poner un int en una variable corta y que asumiremos la responsabilidad. Al ver que se ha indicado explícitamente un tipo más estrecho, el compilador realiza la conversión. ¿Cuál es el resultado? Salida de la consola: -27008 Eso fue un poco inesperado. ¿Por qué exactamente obtuvimos eso? De hecho, todo es muy simple. Originalmente, el valor era 10000000. Se almacenaba en una variable int , que ocupa 32 bits. Esta es su representación binaria:
Ensanchamiento y estrechamiento de tipos primitivos - 3
¡Escribimos este valor en una variable corta , que solo puede almacenar 16 bits! En consecuencia, solo los primeros 16 bits de nuestro número se moverán allí. El resto será descartado. Como resultado, la variable corta recibe el siguiente valor
Ensanchamiento y estrechamiento de tipos primitivos - 4
que en forma decimal es igual a -27008 Es por eso que el compilador le pide que "confirme" indicando una conversión de restricción explícita a un tipo específico. Primero, esto demuestra que estás asumiendo la responsabilidad por el resultado. Y segundo, le dice al compilador cuánto espacio debe asignar cuando ocurre la conversión. Después de todo, en el último ejemplo, si asignáramos un valor int a una variable byte en lugar de un valor corto , solo tendríamos 8 bits a nuestra disposición, no 16, y el resultado sería diferente. Los tipos fraccionarios ( float y double ) tienen su propio proceso para reducir las conversiones. Si intenta convertir un número fraccional en un tipo entero, la parte fraccionaria se descartará.
public static void main(String[] args) {

   double d = 2.7;

   long x = (int) d;
   System.out.println(x);
}
Salida de consola: 2

carbonizarse

Ya sabe que char se usa para mostrar caracteres individuales.
public static void main(String[] args) {

   char c = '!';
   char z = 'z';
   char i = '8';

}
Pero este tipo de datos tiene varias características que es importante comprender. Veamos de nuevo la tabla de rangos de valores:
tipo primitivo Tamaño en memoria Rango de valores
byte 8 bits -128 a 127
corto 16 bits -32768 a 32767
carbonizarse 16 bits 0 a 65536
En t 32 bits -2147483648 al 2147483647
largo 64 bits -9223372036854775808 al 9223372036854775807
flotar 32 bits (2 elevado a -149) a ((2 - (2 elevado a -23)) * 2 elevado a 127)
doble 64 bits (-2 elevado a 63) a ((2 elevado a 63) - 1)
booleano 8 (cuando se usa en matrices), 32 (si no se usa en matrices) verdadero o falso
El rango de 0 a 65536 se indica para el tipo de carácter . Pero ¿qué significa eso? Al fin y al cabo, un char no solo representa números, sino también letras, signos de puntuación… Lo que pasa es que en Java los valores char se almacenan en formato Unicode. Ya nos encontramos con Unicode en una de las lecciones anteriores. Probablemente recuerde que Unicode es un estándar de codificación de caracteres que incluye los símbolos de casi todos los idiomas escritos del mundo. En otras palabras, es una lista de códigos especiales que representan casi todos los caracteres de cualquier idioma. Toda la tabla Unicode es muy grande y, por supuesto, no es necesario aprenderla de memoria. He aquí una pequeña parte de ella: Ensanchamiento y estrechamiento de tipos primitivos - 5 Lo principal es comprender cómo se almacenan los caracteres y recordar que si conoce el código de un carácter en particular, siempre puede producir ese carácter en su programa. Probemos con algún número aleatorio:
public static void main(String[] args) {

   int x = 32816;

   char c = (char) x ;
   System.out.println(c);
}
Salida de la consola: 耰 Este es el formato utilizado para almacenar caracteres en Java. Cada símbolo corresponde a un número: un código numérico de 16 bits (dos bytes). En Unicode, 32816 corresponde al carácter chino 耰. Tome nota del siguiente punto. En este ejemplo, usamos una variable int . Ocupa 32 bits en la memoria, mientras que un char ocupa 16. Aquí elegimos un int , porque nuestro número (32816) no cabe en un short . Aunque el tamaño de un char (al igual que un short ) es de 16 bits, no hay números negativos en el rango de char , por lo que la parte "positiva" del charel rango es el doble de grande (65536 en lugar de 32767 para el tipo corto ). Podemos usar un int siempre que nuestro código se mantenga por debajo de 65536. Pero si crea un valor int mayor que 65536, ocupará más de 16 bits. Y esto resultará en una conversión estrecha
char c = (char) x;
los bits adicionales se descartarán (como se mencionó anteriormente) y el resultado será bastante inesperado.

Características especiales de agregar caracteres y enteros

Veamos un ejemplo inusual:
public class Main {

   public static void main(String[] args) {

      char c = '1';

      int i = 1;

       System.out.println(i + c);
   }
}
Salida de la consola: 50 O_О ¿Qué sentido tiene eso? 1+1. ¿De dónde vienen los 50? Ya sabe que charlos valores se almacenan en la memoria como números en el rango de 0 a 65536, y que estos números son una representación Unicode de un carácter. Ensanchamiento y estrechamiento de tipos primitivos - 6 Cuando agregamos un carácter y algún tipo de número entero, el carácter se convierte al número Unicode correspondiente. En nuestro código, cuando agregamos 1 y '1', el símbolo '1' se convirtió en su propio código, que es 49 (puede verificar esto en la tabla anterior). Por lo tanto, el resultado es 50. Una vez más, tomemos a nuestro viejo amigo 耰 como ejemplo e intentemos sumarlo a algún número.
public static void main(String[] args) {

   char c = '耰';
   int x = 200;

   System.out.println(c + x);
}
Salida de la consola: 33016 Ya descubrimos que 耰 corresponde a 32816. Y cuando sumamos este número y 200, obtenemos nuestro resultado: 33016. :) Como puede ver, el algoritmo aquí es bastante simple, pero no debe olvidarlo .
Comentarios
  • Populares
  • Nuevas
  • Antiguas
Debes iniciar sesión para dejar un comentario
Esta página aún no tiene comentarios