TL; DR
Java armazena em cache instâncias inteiras em caixa de -128
a 127
. Como você está usando ==
para comparar referências de objetos em vez de valores , apenas os objetos em cache corresponderão. Trabalhe com long
valores primitivos não encaixotados ou use .equals()
para comparar seus Long
objetos.
Versão longa (trocadilho intencional)
Por que há problema em comparar a variável longa com valor maior que 127? Se o tipo de dados da variável acima for primitivo (longo), o código funcionará para todos os valores.
Java armazena em cache instâncias de objetos inteiros de -128 a 127 . Dito isto:
- Se você definir como N variáveis longas o valor
127
(em cache ), a mesma instância do objeto será apontada por todas as referências. (N variáveis, 1 instância)
- Se você definir como N variáveis longas o valor
128
( não armazenado em cache ), você terá uma instância de objeto apontada por cada referência. (N variáveis, N instâncias)
É por isso que:
Long val1 = 127L;
Long val2 = 127L;
System.out.println(val1 == val2);
Long val3 = 128L;
Long val4 = 128L;
System.out.println(val3 == val4);
Produz isto:
verdadeiro
falso
Para o valor 127L , como ambas as referências (val1 e val2) apontam para a mesma instância do objeto na memória (em cache), ele retorna true
.
Por outro lado, para o valor 128 , uma vez que não há instância para ele em cache na memória, uma nova é criada para quaisquer novas atribuições para valores em caixa, resultando em duas instâncias diferentes (apontadas por val3 e val4) e retornando false
no comparação entre eles.
Isso acontece apenas porque você está comparando duas Long
referências de objeto , não long
valores primitivos, com o ==
operador. Se não fosse por esse mecanismo de Cache, essas comparações sempre falhariam, então o verdadeiro problema aqui é comparar os valores em caixa com o ==
operador.
Alterar essas variáveis para long
tipos primitivos impedirá que isso aconteça, mas caso você precise manter seu código usando Long
objetos, pode fazer essas comparações com segurança com as seguintes abordagens:
System.out.println(val3.equals(val4)); // true
System.out.println(val3.longValue() == val4.longValue()); // true
System.out.println((long)val3 == (long)val4); // true
(A verificação nula adequada é necessária, mesmo para peças fundidas)
IMO , é sempre uma boa idéia manter os métodos .equals () ao lidar com comparações de objetos.
Links de referência:
.longValue()
.Comparar não-primitivos (também conhecidos como objetos) em Java com
==
compara sua referência em vez de seus valores.Long
é uma classe e, portanto, osLong
valores são Objetos.O problema é que os desenvolvedores Java queriam que as pessoas usassem
Long
como costumavamlong
fornecer compatibilidade, o que levou ao conceito de autoboxing, que é essencialmente o recurso, quelong
-valores serão alterados paraLong
-Objects e vice-versa conforme necessário. O comportamento do autoboxing não é exatamente previsível o tempo todo, pois não é completamente especificado.Portanto, para estar seguro e ter resultados previsíveis, use sempre
.equals()
para comparar objetos e não dependa do autoboxing neste caso:fonte