"Como os desenvolvedores podem criar classes que descrevam números, eles decidiram ser criativos, como desenvolvedores reais."

"Primeiro, eles criaram uma classe abstrata Number, da qual Byte, Short, Integer, Long, Float e Double são derivados. Ela possui métodos que ajudam a converter números em outros tipos numéricos."

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

"Certo. Afinal, você não pode escrever isso:"

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

"Sim, esses tipos não são primitivos. É por isso que usamos os métodos da classe Number:"

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

"Mas ainda há algumas coisas a considerar. Como Integer não é um int, os objetos Integer não podem ser comparados com o clássico operador «==»."

Comparando tipos primitivos
int x = 500;
int y = 500;
x == y; //true
Comparando tipos não primitivos
Integer x = 500;
Integer y = 500;
x == y; //false
x.equals(y); //true

"Exatamente. De alguma forma eu não pensei nisso imediatamente."

"Mas há mais."

"Você está causando um curto-circuito em meus circuitos! O que mais há?"

"Quando atribuímos um valor int a uma variável Integer, o método Integer.valueOf é chamado:"

Código O que realmente acontece
Integer x = 5;
Integer x = Integer.valueOf(5);

"Sim, eu já entendi isso do exemplo acima."

"Mas a função valueOf nem sempre cria um novo objeto Integer."

"Uh, o que você quer dizer com 'nem sempre'?"

"Ele armazena em cache valores de -128 a 127."

Código O que realmente acontece Descrição
Integer x = 300;
Integer y = 300;
Integer z = 300;
Integer x = Integer.valueOf(300);
Integer y = Integer.valueOf(300);
Integer z = Integer.valueOf(300);
As variáveis ​​x, y e z contêm referências 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);
As variáveis ​​x, y e z contêm referências ao mesmo 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);
As variáveis ​​z e t contêm referências ao mesmo objeto.

"Em outras palavras, a situação é esta:"

1)  Se escrevermos «new Integer()», temos a garantia de obter um novo objeto.

2)  Se chamarmos Integer.valueOf(), explicitamente ou através de autoboxing, então o método pode retornar um novo objeto ou um objeto em cache se o argumento de número estiver no intervalo de -128 a 127.

"O que há de tão terrível no método que retorna um objeto do cache?"

"Não importa. Você só precisa saber que às vezes, quando você não está esperando, os objetos podem ser iguais. Tudo com igualdade é complicado. Se compararmos um primitivo com um não primitivo, então eles são comparados como primitivos:"

problema de comparação
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)
Um exemplo ainda mais interessante. A cache entra aqui na foto
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)
Mas o cache não está envolvido aqui
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)

"Ótimo... E como vou memorizar tudo isso?"

"Você não precisa memorizar isso. Você só precisa entender como tudo isso é organizado e o que realmente acontece quando um primitivo e sua contraparte não primitiva entram em jogo."

"Eu também recomendo que você dê uma olhada nos métodos da classe Integer. Ela tem alguns métodos bons e úteis. Você até já usou um deles com frequência."

"Sim, eu me lembro. Integer.parseInt();"