Por que é de 128 == 128 falsa, mas 127 == 127 é verdade quando se comparam wrappers inteiros em Java?
-
19-09-2019 - |
Pergunta
class D {
public static void main(String args[]) {
Integer b2=128;
Integer b3=128;
System.out.println(b2==b3);
}
}
Output:
false
class D {
public static void main(String args[]) {
Integer b2=127;
Integer b3=127;
System.out.println(b2==b3);
}
}
Output:
true
Nota:. Números entre -128 e 127 são verdadeiras
Solução
Quando você compila um literal número em Java e atribuí-lo a um Integer (I
capital), os emite compilador:
Integer b2 =Integer.valueOf(127)
Esta linha de código também é gerado quando você usa autoboxing.
valueOf
é implementado de tal forma que certos números são "agrupados", e retorna a mesma instância para valores menores do que 128.
A partir do código-fonte java 1.6, linha 621:
public static Integer valueOf(int i) {
if(i >= -128 && i <= IntegerCache.high)
return IntegerCache.cache[i + 128];
else
return new Integer(i);
}
O valor da high
pode ser configurado para outro valor, com a propriedade do sistema.
-Djava.lang.Integer.IntegerCache.high = 999
Se você executar o seu programa com que a propriedade do sistema, ele irá imprimir verdade!
A conclusão óbvia: nunca confiar em duas referências serem idênticos, sempre compará-los com o método .equals()
Assim b2.equals(b3)
irá imprimir verdadeiro para todos os valores logicamente iguais de B2, B3.
Note que o cache Integer
não está lá por motivos de desempenho, mas sim em conformidade com o JLS, seção 5.1.7 ; identidade do objeto deve ser dada para valores -128 a 127, inclusive.
Integer # valueOf (int) também documenta esse comportamento:
este método é susceptível de produzir espaço e tempo significativamente melhor desempenho pelo cache valores frequentemente solicitados. Este método será sempre valores de cache na faixa de -128 a 127, inclusive, e pode armazenar em cache outros valores fora desta faixa.
Outras dicas
Autoboxing caches -128 a 127. Isso é especificado nas JLS ( 5.1.7 ).
Se o valor p ser encaixotado é verdadeiro, falso, um byte, um char na faixa \ u0000 para \ u007f, ou um int ou short número entre -128 e 127, em seguida, deixar R1 e R2 ser os resultados de quaisquer duas conversões de boxe de p. É sempre o caso que R1 == r2.
Uma regra simples para lembrar quando se lida com objetos é -. Uso .equals
se você quiser verificar se os dois objetos são "iguais", o uso ==
quando você quer ver se eles apontam para a mesma instância
Usando tipos de dados primitivos, ints, produziria verdade em ambos os casos, a saída esperada.
No entanto, desde que você está usando Integer objetos o operador == tem um significado diferente.
No contexto de objetos, == verifica se as variáveis ??se referem ao mesmo objeto de referência.
Para comparar o valor dos objetos que você deve usar o método equals () Por exemplo.
b2.equals(b1)
que indicará se b2 é inferior a b1, maior que, ou igual a (verifique o API para mais detalhes)
É otimização de memória em Java relacionados.
Para economizar memória, Java 'reutilizações' tudo o wrapper objetos valores cujas cair nos seguintes intervalos:
Todos os valores booleanos (verdadeiro e falso)
Os valores Todos Byte
Todos os valores de caracteres de \ u0000 para \ u007f (ou seja, de 0 a 127 em decimal)
Os valores Todos curto e inteiro de -128 a 127.
Tenha um olhar para o Integer.java, se o valor estiver entre -128 e 127, ele irá utilizar a piscina em cache, então (Integer) 1 == (Integer) 1
enquanto (Integer) 222 != (Integer) 222
/**
* Returns an {@code Integer} instance representing the specified
* {@code int} value. If a new {@code Integer} instance is not
* required, this method should generally be used in preference to
* the constructor {@link #Integer(int)}, as this method is likely
* to yield significantly better space and time performance by
* caching frequently requested values.
*
* This method will always cache values in the range -128 to 127,
* inclusive, and may cache other values outside of this range.
*
* @param i an {@code int} value.
* @return an {@code Integer} instance representing {@code i}.
* @since 1.5
*/
public static Integer valueOf(int i) {
assert IntegerCache.high >= 127;
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}
Eu escrevi o seguinte como este problema não é apenas específico para Integer. Minha conclusão é que mais frequentemente se você usar a API incorretamente, você peitoril ver o comportamento incorreto. Usá-lo corretamente e você deve ver o comportamento correto:
public static void main (String[] args) {
Byte b1=127;
Byte b2=127;
Short s1=127; //incorrect should use Byte
Short s2=127; //incorrect should use Byte
Short s3=128;
Short s4=128;
Integer i1=127; //incorrect should use Byte
Integer i2=127; //incorrect should use Byte
Integer i3=128;
Integer i4=128;
Integer i5=32767; //incorrect should use Short
Integer i6=32767; //incorrect should use Short
Long l1=127L; //incorrect should use Byte
Long l2=127L; //incorrect should use Byte
Long l3=13267L; //incorrect should use Short
Long l4=32767L; //incorrect should use Short
Long l5=2147483647L; //incorrect should use Integer
Long l6=2147483647L; //incorrect should use Integer
Long l7=2147483648L;
Long l8=2147483648L;
System.out.print(b1==b2); //true (incorrect) Used API correctly
System.out.print(s1==s2); //true (incorrect) Used API incorrectly
System.out.print(i1==i2); //true (incorrect) Used API incorrectly
System.out.print(l1==l2); //true (incorrect) Used API incorrectly
System.out.print(s3==s4); //false (correct) Used API correctly
System.out.print(i3==i4); //false (correct) Used API correctly
System.out.print(i5==i6); //false (correct) Used API correctly
System.out.print(l3==l4); //false (correct) Used API correctly
System.out.print(l7==l8); //false (correct) Used API correctly
System.out.print(l5==l6); //false (correct) Used API incorrectly
}