Java tiene ocho tipos primitivos y todo lo demás son objetos. La diferencia importa más de lo que parece: un primitivo guarda el valor, un objeto guarda una referencia, y un primitivo nunca puede ser null.
También te puede interesar
Los ocho primitivos
| Tipo | Tamaño | Rango | Por omisión |
|---|---|---|---|
byte | 1 byte | −128 .. 127 | 0 |
short | 2 bytes | −32.768 .. 32.767 | 0 |
int | 4 bytes | −2.147.483.648 .. 2.147.483.647 | 0 |
long | 8 bytes | −9.223.372.036.854.775.808 .. 9.223.372.036.854.775.807 | 0L |
float | 4 bytes | ±3,4 × 1038, con unos 7 dígitos buenos | 0.0f |
double | 8 bytes | ±1,8 × 10308, con unos 15 dígitos buenos | 0.0d |
boolean | sin definir | true o false | false |
char | 2 bytes | 0 .. 65.535 (una unidad UTF-16) | '\u0000' |
Los rangos no hay que aprendérselos: están en las constantes de las clases envoltorio, y así es como conviene consultarlos.
System.out.println("int " + Integer.MIN_VALUE + " .. " + Integer.MAX_VALUE);
System.out.println("long " + Long.MIN_VALUE + " .. " + Long.MAX_VALUE);
System.out.println("double " + Double.MIN_VALUE + " .. " + Double.MAX_VALUE);salidaint -2147483648 .. 2147483647 long -9223372036854775808 .. 9223372036854775807 double 4.9E-324 .. 1.7976931348623157E308
MIN_VALUE: en los enteros es el más negativo, pero en float y double es el positivo más pequeño que se puede representar, no el más negativo. El más negativo es -Double.MAX_VALUE. Es una asimetría que despista a todo el mundo la primera vez.Cómo se escriben
byte b = 10; short s = 266; int i = 1231232; long l = 10_000_000_000L; // la L final es obligatoria si no cabe en un int float f = 4.15f; // la f final es obligatoria double d = 12312.2; // por omisión, un decimal es double boolean existe = true; char c = 'a'; char salto = '\n';
javac SinL.javaSinL.java:3: error: integer number too large
long l = 10000000000;
^
1 errorLos guiones bajos de 10_000_000_000L no son decorativos ni cambian el valor: el compilador los ignora y están para que un número largo se lea. Y sin la L, ese literal no compila, porque por omisión se interpreta como int y no cabe; el error de arriba es el que da javac.
El valor por omisión existe, pero no siempre
public class Tipos {
static int campoSinValor;
static boolean banderaSinValor;
static String textoSinValor;
public static void main(String[] args) {
System.out.println("int sin valor = " + campoSinValor);
System.out.println("boolean sin valor = " + banderaSinValor);
System.out.println("String sin valor = " + textoSinValor);
}
}salidaint sin valor = 0 boolean sin valor = false String sin valor = null
variable x might not have been initialized, y hace bien.Dos cosas que sorprenden
int grande = Integer.MAX_VALUE;
System.out.println("MAX_VALUE + 1 = " + (grande + 1));
System.out.println("0.1 + 0.2 = " + (0.1 + 0.2));salidaMAX_VALUE + 1 = -2147483648 0.1 + 0.2 = 0.30000000000000004
La primera es el desbordamiento: al pasarse del máximo, un int da la vuelta y aparece en el mínimo. Java no avisa. Si el número puede crecer, usa long, y si tiene que ser exacto y grande, BigInteger.
La segunda es que double y float son binarios: 0,1 y 0,2 no tienen representación exacta en base dos, igual que 1/3 no la tiene en base diez. Para dinero no se usan nunca; para eso está BigDecimal.
char no es un carácter, es media cosa
String emoji = "\uD83D\uDE80"; // un cohete
System.out.println("length() = " + emoji.length());
System.out.println("codePointCount = " + emoji.codePointCount(0, emoji.length()));salidalength() = 2 codePointCount = 1
Un char guarda una unidad de UTF-16, que es suficiente para las letras latinas, los acentos y la eñe, pero no para los emojis ni para buena parte del chino y el japonés: esos ocupan dos. Por eso length() devuelve 2 para un solo símbolo. Si vas a contar caracteres de verdad, codePointCount.
Los no primitivos
Todo lo demás —String, los arreglos, las listas, tus propias clases— son objetos. Se distinguen en tres cosas: empiezan por mayúscula, pueden valer null y tienen métodos.
String cad = "Esto es una cadena"; System.out.println(cad.toUpperCase()); System.out.println(cad.length());
String es además inmutable: toUpperCase() no cambia la cadena, devuelve otra. Y por eso dos cadenas se comparan con equals, nunca con ==, que compara si son el mismo objeto en memoria.
var y dejar que el compilador deduzca el tipo: var i = 10; es un int y var cad = "hola"; es un String. No es tipado dinámico —el tipo se fija al compilar y no cambia—, solo te ahorra escribirlo.Todo el código se compiló y se ejecutó con Java 25 LTS en un contenedor limpio antes de publicar esta página; las salidas están copiadas de esa ejecución.