Escrevi um trecho de código Java que está sendo executado em um loop infinito.
Abaixo está o código:
public class TestProgram {
public static void main(String[] args){
Integer i = new Integer(0);
Integer j = new Integer(0);
while(i<=j && j<=i && i!=j){
System.out.println(i);
}
}
}
No código acima, ao ver a condição no while
loop, a princípio parece que o programa não entrará no while
loop. Mas na verdade é um loop infinito e continua imprimindo o valor.
O que esta acontecendo aqui?
i<=j && j<=i && i!=j
essa condição sempre é avaliada como verdadeira. Pegue um pedaço de papel e avalie que você vai pegá-lo :)i
ouj
, quando espera que o loop termine?i<=j
ej<=i
você pode concluir, issoi == j
, que contradiz o último termo. Portanto, toda a expressão é avaliada como falsa e o while não seria inserido. O ponto chave é a identidade do objeto aqui!Respostas:
i <= j
é avaliado comotrue
, porque o unboxing automático acontece para comparações internas e, em seguida,i
ej
mantém o valor padrão0
,.j <= i
é avaliadotrue
devido ao motivo acima.i != j
é avaliado comotrue
, porquei
ej
são objetos diferentes. E ao comparar objetos, não há necessidade de desempacotamento automático.Todas as condições são verdadeiras e você não está mudando
i
ej
em loop, portanto, ele está funcionando infinitamente.fonte
Integer.valueOf(0) == Integer.valueOf(0)
é sempre avaliado como verdadeiro porque, neste caso, o mesmo objeto é retornado (consulte IntegerCache grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/… )Porque você está comparando
0 < = 0 (true) // unboxing
0 > = 0 (true) // unboxing
reference != secondReference (true)
como você está criando objetos, não uma comparação primitiva. Portanto, é avaliado comowhile(true) { // Never ending loop }
.fonte
Os objetos inteiros são diferentes. É diferente do tipo básico interno.
Veja esta resposta: Como comparar corretamente dois inteiros em Java?
A
i != j
parte é verdadeira, que você esperava que fosse falsa.fonte
true
causa do autoboxing. No caso de # 3, o autoboxing não se aplica e a comparação ocorre no nível do objeto (localização da memória).O loop não está terminando porque sua condição é verdadeira (i! = J é verdadeira porque existem 2 objetos diferentes, use Integer.valueOf em vez disso) e dentro do loop os valores não estão mudando, então sua condição permanece verdadeira para sempre.
fonte
Os objetos inteiros são diferentes. É diferente do tipo básico interno. então você pode simplesmente fazer assim. o que você faz é apenas comparar o objeto e, claro, o resultado é verdadeiro.
fonte
Existem dois casos diferentes que devemos entender primeiro,
caso 1:
caso 2:
ambos são diferentes, como
no caso 1:
i!=j
serátrue
porque ambos fazem referência a dois objetos diferentes no heap e não podem ser iguais. Masno caso 2:
i==j
serátrue
porque ambos 10 são literais inteiros e Java mantémpool for Integer literals
que têm valor(-128 <= X <= 127)
. Portanto, neste caso 10 <= 127 resultados verdadeiros, então ambos terão referência ao mesmo objeto.fonte
Talvez a razão seja que 'i' e 'j' são objetos, e comparação de objetos não é o mesmo que comparação de referência de objetos. Considere usar! I.equals (j) em vez de i! = J
fonte
O programa continua exibindo o mesmo valor de
i
porque você não está incrementando ou diminuindo o valor dei
ouj
. A condição em for sempre continua avaliando como verdadeira, portanto, é um loop infinito.fonte
i!=j
parte que surpreendentemente avalia como verdadeira e não sobre as<=
comparações.As comparações <= e> = usarão o valor não encaixotado 0, enquanto o! = Comparará as referências e terá êxito, pois são objetos diferentes.
Mesmo isso também funcionará i, e
mas isso não:
O motivo é porque Integer usa internamente o cache para objetos Integer entre -128 e 127 e retorna instâncias desse cache para o intervalo que cobre. Não tenho certeza, mas acho que você também pode alterar seu valor máximo no pacote "java.lang.Integer.IntegerCache.high".
Para melhor compreensão, verifique o url: https://www.owasp.org/index.php/Java_gotchas#Immutable_Objects_.2F_Wrapper_Class_Caching
fonte
você tem que saber que é um pouco diferente em && isto e isto & quando você usa && então quando a primeira condição é verdadeira então ele verifica a segunda condição se for falsa então não verificou a terceira condição porque no operador & se uma condição for falsa todas as declaração é falsa se usar || então, se for verdadeiro, então ele retornará verdadeiro em seu código porque i e j são iguais primeiro e a segunda condição é verdadeira, então na terceira condição será falso porque eles são iguais e enquanto a condição é falsa.
fonte