"Dado que los desarrolladores podían crear clases que describieran números, decidieron ser creativos, como los desarrolladores reales".

"Primero, idearon una clase numérica abstracta, de la que se derivan Byte, Short, Integer, Long, Float y Double. Tiene métodos que ayudan a convertir números a otros tipos numéricos".

Métodos de la clase Number
1
int intValue()
2
long longValue()
3
float floatValue()
4
double doubleValue()
5
byte byteValue()
6
short shortValue()

"Correcto. Después de todo, no puedes escribir esto:"

Long x = 100000;
Integer y = (Integer) x;

"Sí, estos tipos no son primitivos. Es por eso que usamos los métodos de la clase Número:"

Long x = 100000;
Integer y = x.intValue();

"Pero todavía hay un par de cosas a considerar. Debido a que Integer no es un int, los objetos Integer no se pueden comparar con el operador clásico «==»".

Comparando tipos primitivos
int x = 500;
int y = 500;
x == y; //true
Comparación de tipos no primitivos
Integer x = 500;
Integer y = 500;
x == y; //false
x.equals(y); //true

"Exactamente. De alguna manera no pensé en eso de inmediato".

Pero hay más.

"¡Estás cortocircuitando mis circuitos! ¿Qué más hay?"

"Cuando asignamos un valor int a una variable Integer, se llama al método Integer.valueOf:"

Código lo que realmente sucede
Integer x = 5;
Integer x = Integer.valueOf(5);

"Sí, ya entendí eso del ejemplo anterior".

"Pero, la función valueOf no siempre crea un nuevo objeto Integer".

"Uh, ¿qué quieres decir con 'no siempre'?"

"Almacena en caché valores de -128 a 127".

Código lo que realmente sucede Descripción
Integer x = 300;
Integer y = 300;
Integer z = 300;
Integer x = Integer.valueOf(300);
Integer y = Integer.valueOf(300);
Integer z = Integer.valueOf(300);
Las variables x, y y z contienen referencias a diferentes objetos
Integer x = 100;
Integer y = 100;
Integer z = 100;
Integer x = Integer.valueOf(100);
Integer y = Integer.valueOf(100);
Integer z = Integer.valueOf(100);
Las variables x, y y z contienen referencias al mismo objeto.
Integer x = new Integer(10)
Integer y = new Integer(10)
Integer z = 10;
Integer t = 10;
Integer x = new Integer(10)
Integer y = new Integer(10)
Integer z = Integer.valueOf(10);
Integer t = Integer.valueOf(10);
Las variables z y t contienen referencias al mismo objeto.

"En otras palabras, la situación es esta:"

1)  Si escribimos «nuevo entero()», entonces estamos garantizados para obtener un nuevo objeto.

2)  Si llamamos a Integer.valueOf(), explícitamente o mediante autoboxing, entonces el método puede devolver un nuevo objeto o un objeto almacenado en caché si el argumento numérico está en el rango de -128 a 127.

"¿Qué tiene de terrible que el método devuelva un objeto del caché?"

"No importa. Solo necesitas saber que a veces, cuando no lo esperas, los objetos pueden ser iguales. Todo con igualdad es complicado. Si comparamos un primitivo con un no primitivo, entonces se comparan como primitivos:"

Problema de comparación
int x = 300;
Integer y = 300;
Integer z = 300;

x == y; //true (comparison based on primitive value)
x == z; //true (comparison based on primitive value)
y == z; //false (comparison based on references)
Un ejemplo aún más interesante. El caché entra en escena aquí.
int x = 100;
Integer y = 100;
Integer z = 100;

x == y; //true (comparison based on primitive value)
x == z; //true (comparison based on primitive value)
y == z; //true (comparison based on references; they point to the same object)
Pero el caché no está involucrado aquí.
int x = 100;
Integer y = new Integer(100);
Integer z = 100;

x == y; //true (comparison based on primitive value)
x == z; //true (comparison based on primitive value)
y == z; //false (comparison based on references; they point to different objects)

"Genial... ¿Y cómo voy a memorizar todo esto?"

"No necesitas memorizar esto. Solo necesitas entender cómo está todo organizado y qué sucede realmente cuando entran en juego un primitivo y su contraparte no primitiva".

"También te recomiendo que mires los métodos de la clase Integer. Tiene bastantes métodos buenos y útiles. Incluso has usado uno de ellos con bastante frecuencia".

"Sí, lo recuerdo. Integer.parseInt();"