Menu

Tipos de datos en Java: primitivos, tipos de referencia y valores por defecto

Los tipos de datos de Java explicados: los ocho tipos primitivos, los tipos de referencia, los valores por defecto, los literales y sufijos, el desbordamiento y cuándo usar cada tipo numérico.

Esta página incluye editores ejecutables: edita, ejecuta y ve el resultado al instante.

Dos familias: primitivos y referencias

Todo valor en Java tiene un tipo, y ese tipo pertenece a una de dos familias. Los tipos primitivos almacenan un valor crudo directamente: un número, un único carácter o un verdadero/falso. Los tipos de referencia almacenan una referencia (un puntero) a un objeto que vive en otra parte de la memoria: String, los arreglos y todas las clases que tú o las bibliotecas definís.

La distinción importa porque los primitivos son ligeros y se copian por valor, mientras que las variables de referencia apuntan a objetos compartidos. Empieza por los ocho primitivos: son la base sobre la que se construye todo lo demás.

Los ocho tipos primitivos

Java tiene exactamente ocho tipos primitivos integrados. Seis son números, uno es un carácter y uno es un booleano:

Algunas cosas que conviene notar desde el principio: los guiones bajos en 2_000_000 son solo separadores visuales que el compilador ignora, los sufijos L y f son obligatorios (más sobre esto abajo), y char usa comillas simples mientras que un String usaría comillas dobles.

Cómo elegir un tipo numérico

Casi nunca necesitas byte ni short: solo ahorran memoria en arreglos enormes. Las decisiones reales están entre int/long para enteros y float/double para decimales.

TipoTamañoÚsalo cuando
int32 bitsEl valor por defecto para enteros (hasta ~2.100 millones)
long64 bitsValores por encima de ~2.000 millones: marcas de tiempo en milisegundos, tamaños de archivo
double64 bitsEl valor por defecto para decimales - buena precisión
float32 bitsSolo cuando la memoria es escasa y la precisión puede resentirse

La trampa es el desbordamiento. Un int se enrolla silenciosamente cuando supera su rango: ningún error, solo una respuesta equivocada:

maxInt + 1 se desborda a -2147483648 porque ambos operandos son int y el resultado sigue siendo un int. Convertir un lado a long primero hace el cálculo en 64 bits. Cuando un valor puede ser grande - especialmente los milisegundos desde 1970 - recurre a long.

Literales y sus sufijos

Un literal numérico simple tiene un tipo por defecto, y eso causa problemas. 100 es un int; 3.14 es un double. Para escribir un literal long o float debes añadir un sufijo:

Quita la L de 8_000_000_000L y el código no compilará, porque el literal supera el rango de int antes de llegar siquiera a la variable long. Quita la f de 0.5f y Java se queja de que un double no puede asignarse a un float sin una conversión. El sufijo no distingue entre mayúsculas y minúsculas, pero usa la L mayúscula: una l minúscula se parece exactamente al dígito 1.

char es un número disfrazado

Un char almacena una unidad de código Unicode de 16 bits, lo que significa que funciona también como un pequeño entero sin signo. Puedes hacer aritmética con él y convertirlo de ida y vuelta con una conversión:

Esto resulta útil de vez en cuando para desplazar letras, pero no te apoyes en ello para manejar texto: para eso está String. Ten en cuenta que char usa comillas simples ('A'); las comillas dobles ("A") crean un String de un solo carácter, que es un tipo completamente distinto.

Valores por defecto (y la trampa de las variables locales)

Los campos y los elementos de arreglos que no inicializas reciben un valor por defecto razonable. Pero esto solo se aplica a los campos y las posiciones de los arreglos: las variables locales no reciben ningún valor por defecto, y usar una antes de asignarle un valor es un error de compilación, no una sorpresa en tiempo de ejecución.

Si en cambio escribieras int x; System.out.println(x); dentro de main, el compilador lo rechazaría con "variable x might not have been initialized". Esa rigurosidad es una ventaja: te impide leer basura. Los valores por defecto a recordar: los tipos numéricos 0, boolean false, char ' ' y todo tipo de referencia null.

A continuación: Strings

String es el tipo de referencia que más vas a usar: texto, valores unidos, entrada del usuario. Se comporta de forma distinta a los primitivos vistos aquí: es un objeto, es inmutable y comparar cadenas tiene sus propias trampas. La siguiente página lo cubre.

Preguntas frecuentes

¿Cuántos tipos de datos hay en Java?

Java tiene ocho tipos primitivos: byte, short, int, long, float, double, char y boolean. Todo lo demás - String, los arreglos y cualquier objeto - es un tipo de referencia. Así que el número de primitivos integrados es fijo en ocho, mientras que los tipos de referencia son ilimitados porque tú (y las bibliotecas) defines nuevas clases.

¿Cuál es la diferencia entre int y long en Java?

Ambos almacenan números enteros, pero int es de 32 bits (rango de unos ±2.100 millones) y long es de 64 bits (rango de unos ±9,2 trillones). Usa int por defecto; cambia a long cuando un valor pueda superar los dos mil millones: marcas de tiempo en milisegundos, tamaños de archivo, contadores grandes. Un literal long necesita el sufijo L, por ejemplo long big = 10000000000L;.

¿Cuál es el valor por defecto de un int en Java?

Un campo de tipo int tiene como valor por defecto 0, pero solo los campos y los elementos de arreglos reciben valores por defecto. Un long toma 0L, un double 0.0, un boolean false, un char '\u0000' y cualquier tipo de referencia null. Las variables locales no reciben ningún valor por defecto: debes asignarles uno antes de usarlas o el código no compilará.

Coddy programming languages illustration

Aprende a programar con Coddy

COMENZAR