Java tiene ocho tipos primitivos, y guardan valores directos en lugar de referencias a objetos. Cuatro son tipos enteros: byte (8 bits), short (16 bits), int (32 bits) y long (64 bits), todos con signo. Dos son de punto flotante: float (32 bits) y double (64 bits). char es un valor de 16 bits sin signo que almacena una unidad de código UTF-16, así que puede usarse en aritmética, y boolean solo contiene true o false. A diferencia de otros lenguajes, un boolean de Java nunca es un número: if (1) no compila.
Un literal es un valor escrito directamente en el código fuente. Un número entero simple como 42 es un literal int, por lo que un valor demasiado grande para int necesita el sufijo L: long big = 3_000_000_000L; compila, pero el mismo número sin L es un error de compilación aunque el destino sea un long. Un número con punto decimal, como 3.14, es un literal double, así que float f = 3.14; falla y debes escribir 3.14f o hacer un cast. Los literales de carácter usan comillas simples ('A', '\n', 'A').
Los literales enteros pueden escribirse en cuatro bases. Decimal es la base por defecto. Un 0 inicial indica octal (017 es 15), 0x o 0X indica hexadecimal (0x1F es 31), y 0b o 0B indica binario (0b101 es 5). La regla del octal es una trampa clásica: 010 es 8, no 10, y 09 no compila porque 9 no es un dígito octal.
Los guiones bajos pueden separar dígitos para mejorar la legibilidad, como en 1_000_000 o 0b1010_0101. La regla es que un guion bajo debe estar entre dos dígitos. Por eso son ilegales: un guion bajo al inicio o al final (_100, 100_), uno junto al punto decimal (1_.5, 1._5), uno justo antes de un sufijo (10_L, 2.0_f) y uno inmediatamente después del prefijo 0x o 0b (0x_FF). Varios guiones bajos seguidos están bien (1__000), y también uno después del cero inicial de un literal octal (0_17), porque ese cero cuenta como dígito.
Los valores por defecto se aplican solo a los campos (variables de instancia y estáticas) y a los elementos de arreglos. Los campos numéricos toman cero por defecto (0, 0L, 0.0f, 0.0), char toma '\u0000', boolean toma false, y todo tipo de referencia toma null. Las variables locales nunca reciben valor por defecto. Leer una variable local antes de que haya sido asignada de forma definitiva es un error de compilación, algo que al examen le gusta esconder dentro de una rama if.
int[] nums = new int[3]; // {0, 0, 0}
boolean[] flags = new boolean[2]; // {false, false}
int x;
// System.out.println(x); // no compila: x no está inicializada
int hex = 0xFF, oct = 010, bin = 0b11;
System.out.println(hex + oct + bin); // 255 + 8 + 3 = 266
Términos clave
- Primitive type (tipo primitivo)
- Uno de los ocho tipos de valor integrados (byte, short, int, long, float, double, char, boolean) que no son objetos.
- Literal
- Un valor fijo escrito en el código fuente, como 42, 3.5f, 'x' o 0b1010.
- Octal literal (literal octal)
- Un literal entero con un 0 inicial, que se lee en base 8, por lo que 010 equivale a 8.
- Default value (valor por defecto)
- El valor que recibe automáticamente un campo o elemento de arreglo: 0, false, '\u0000' o null. Las variables locales no tienen ninguno.
Un servicio de pagos guarda montos en centavos como long. Un desarrollador escribe long limit = 5_000_000_000; y la compilación falla, porque el literal sigue siendo un literal int y está fuera de rango. Agregar L (5_000_000_000L) lo corrige, y los guiones bajos mantienen el número legible en la revisión de código.
Comprueba lo que sabes
¿Compila float price = 9.99;?
No. 9.99 es un literal double, y asignar un double a un float es una conversión de estrechamiento. Escribe 9.99f o haz cast con (float).
¿Qué imprime System.out.println(012 + 0x10);?
26. 012 es octal para 10 y 0x10 es hexadecimal para 16.
¿Cuál de estos es legal: 1_000, _1000, 0x_10, 1000_L?
Solo 1_000. Los demás ponen un guion bajo al inicio, justo después del prefijo 0x o justo antes del sufijo L.