Eu sei que se você comparar um número inteiro primitivo em caixa com uma constante como:
Integer a = 4;
if (a < 5)
a
será automaticamente retirado da caixa de seleção e a comparação funcionará.
No entanto, o que acontece quando você está comparando duas caixas Integers
e deseja comparar a igualdade ou menor que / maior que?
Integer a = 4;
Integer b = 5;
if (a == b)
O código acima resultará na verificação para ver se eles são o mesmo objeto ou será desassociado automaticamente nesse caso?
A respeito:
Integer a = 4;
Integer b = 5;
if (a < b)
?
java
integer
autoboxing
shmosel
fonte
fonte
==
vez deequals
produzir o resultado correto, isso pode ser porque os números em caixa estão sendo internados ou reutilizados (como uma otimização do compilador, presumivelmente). O motivo para fazer essa pergunta é descobrir o que está acontecendo internamente, não o que parece estar acontecendo. (Pelo menos, é por isso que estou aqui.)Respostas:
Não, == entre Inteiro, Longo etc verificará a igualdade de referência - ou seja,
isso irá verificar se
x
e sey
referir ao mesmo objeto em vez de objetos iguais .assim
é garantido para imprimir
false
. A inclusão de valores "pequenos" autoboxed pode levar a resultados complicados:Isso será impresso
true
devido às regras do boxe ( seção 5.1.7 do JLS ). Ainda é usada a igualdade de referência, mas as referências são realmente iguais.Pessoalmente, eu usaria:
ou
Como você diz, para qualquer comparação entre um tipo de invólucro (
Integer
,Long
etc) e um tipo numérico (int
,long
etc), o valor do tipo de invólucro não é colocado em caixa e o teste é aplicado aos valores primitivos envolvidos.Isso ocorre como parte da promoção numérica binária ( seção 5.6.2 do JLS ). Veja a documentação de cada operador individual para ver se ela é aplicada. Por exemplo, nos documentos para
==
e!=
( JLS 15.21.1 ):e para
<
,<=
,>
e>=
( JLS 15.20.1 )Observe como nada disso é considerado como parte da situação em que nenhum tipo é um tipo numérico.
fonte
x.compareTo(y) < 0
vez dex < y
?==
ainda testará a igualdade de objetos. É fácil ser enganado, no entanto:Seus exemplos com desigualdades funcionarão, pois não estão definidos em Objetos. No entanto, com a
==
comparação, a igualdade de objetos ainda será verificada. Nesse caso, quando você inicializa os objetos de uma primitiva in a box, o mesmo objeto é usado (para a e b). Essa é uma otimização aceitável, pois as classes de caixa primitivas são imutáveis.fonte
200
, ambos os testes serão impressosfalse
.equals
ser chamado".Desde o Java 1.7, você pode usar o Objects.equals :
fonte
==
verifica a igualdade de referência, no entanto, ao escrever código como:Java é inteligente o suficiente para reutilizar o mesmo imutável para
a
eb
, então isso é verdade:a == b
. Curioso, escrevi um pequeno exemplo para mostrar onde o java para de otimizar desta maneira:Quando eu compilo e executo isso (na minha máquina), recebo:
fonte
A minha opinião é usar um unário
+
para acionar o unboxing de um dos operandos ao verificar a igualdade de valor e simplesmente usar os operadores matemáticos. A justificativa a seguir:Já foi mencionado que
==
comparação paraInteger
é comparação de identidade, o que geralmente não é o que um programador deseja e que o objetivo é fazer comparação de valor; Ainda assim, eu fiz um pouco de ciência sobre como fazer essa comparação com mais eficiência, tanto em termos de compactação de código, correção e velocidade.Eu usei o monte de métodos usual:
e obteve esse código após a compilação e descompilação:
Como você pode ver facilmente, o método 1 chama
Integer.equals()
(obviamente), os métodos 2-4 resultam exatamente no mesmo código , desembrulhando os valores por meio de.intValue()
e comparando-os diretamente, e o método 5 apenas aciona uma comparação de identidade, sendo a maneira incorreta de comparar valores.Como (como já mencionado por exemplo, JS)
equals()
incorre em uma sobrecarga (é necessário fazerinstanceof
e uma conversão não verificada), os métodos 2 a 4 funcionam exatamente com a mesma velocidade, notavelmente melhor que o método 1 quando usado em loops apertados, já que o HotSpot não é provável otimizar os elencos &instanceof
.É bem parecido com outros operadores de comparação (por exemplo,
<
/>
) - eles acionam o unboxing, enquanto o usocompareTo()
não - mas desta vez, a operação é altamente otimizável pelo HS, poisintValue()
é apenas um método getter (principal candidato a ser otimizado).Na minha opinião, a versão 4 raramente usada é a maneira mais concisa - todo desenvolvedor experiente de C / Java sabe que o unary plus é na maioria dos casos igual a convertido para
int
/.intValue()
- embora possa ser um pouco WTF para alguns (principalmente aqueles que não usar o unário mais durante a vida útil), mostra sem dúvida a intenção de maneira mais clara e concisa - mostra que queremos umint
valor de um dos operandos, forçando o outro valor a desmarcar também. Também é indiscutivelmente o mais semelhante ài1 == i2
comparação regular usada paraint
valores primitivos .Meu voto é para
i1 == +i2
&i1 > i2
style paraInteger
objetos, tanto por questões de desempenho quanto de consistência. Também torna o código portável para primitivas sem alterar nada além da declaração de tipo. Usar métodos nomeados parece introduzir ruído semântico para mim, semelhante aobigInt.add(10).multiply(-3)
estilo muito criticado .fonte
unary +
(mais unário), ver, por exemplo stackoverflow.com/questions/2624410/...Chamando
Funcionará na maioria das vezes, mas não é garantido que funcione sempre, portanto, não o use.
A maneira mais adequada de comparar duas classes Inteiras para igualdade, assumindo que elas sejam nomeadas 'a' e 'b', é chamar:
Você também pode usar esse caminho que é um pouco mais rápido.
Na minha máquina, 99 bilhões de operações levaram 47 segundos usando o primeiro método e 46 segundos usando o segundo método. Você precisaria comparar bilhões de valores para ver qualquer diferença.
Observe que 'a' pode ser nulo, pois é um objeto. A comparação dessa maneira não causará uma exceção de ponteiro nulo.
Para comparar maior e menor que, use
fonte
if (a==b)
funciona apenas para valores pequenos e não funciona na maioria das vezes.Devemos sempre usar o método equals () para comparação de dois números inteiros. É a prática recomendada.
Se compararmos dois números inteiros usando ==, isso funcionaria para determinado intervalo de valores inteiros (número inteiro de -128 a 127) devido à otimização interna da JVM.
Veja exemplos:
Caso 1:
No caso acima, a JVM usa o valor de aeb do conjunto em cache e retorna a mesma instância do objeto (portanto, endereço de memória) do objeto inteiro e obtemos os dois iguais. Sua otimização é feita pela JVM para determinados valores de intervalo.
Caso 2: Nesse caso, aeb não são iguais porque não vem com o intervalo de -128 a 127.
A maneira certa:
Eu espero que isso ajude.
fonte
No meu caso, eu tive que comparar dois
Integer
s para a igualdade, onde ambos poderiam estarnull
. Pesquisou um tópico semelhante, não encontrou nada de elegante para isso. Veio com um simples utilitário de funções.fonte
Como o método de comparação deve ser feito com base no tipo int (x == y) ou na classe Inteiro (x.equals (y)) com o operador correto
fonte
esse método compara dois números inteiros com verificação nula, consulte testes
fonte
Objects.equals(x,y)
método em vez de usar o seu próprio método.