He escrito un fragmento de código Java que se ejecuta en un bucle infinito.
A continuación se muestra el 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);
}
}
}
En el código anterior, mientras ve la condición en el while
ciclo, al principio parece que ese programa no entrará en el while
ciclo. Pero en realidad es un ciclo infinito y sigue imprimiendo el valor.
¿Que está sucediendo aquí?
i<=j && j<=i && i!=j
esta condición siempre se evalúa como verdadera. Solo toma un pedazo de papel y evalúa que lo atraparás :)i
oj
, ¿cuándo esperaría que terminara el ciclo?i<=j
yj<=i
se puede concluir, esoi == j
, que contradice el último término. Por lo tanto, toda la expresión se evalúa como falsa y no se ingresaría el while. ¡El punto clave es la identidad del objeto aquí!Respuestas:
i <= j
se evalúatrue
, porque el unboxing automático ocurre para las comparaciones int y luego tantoi
yj
mantenga el valor predeterminado,0
.j <= i
es evaluado paratrue
debido a la razón anterior.i != j
se evalúa atrue
, porque tantoi
yj
son objetos diferentes. Y al comparar objetos, no es necesario un desempaquetado automático.Todas las condiciones son verdaderas y no está cambiando
i
nij
en bucle, por lo que se ejecuta infinitamente.fuente
Integer.valueOf(0) == Integer.valueOf(0)
siempre se evalúa como verdadero porque en este caso se devuelve el mismo objeto (consulte IntegerCache grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/… )Porque estas comparando
0 < = 0 (true) // unboxing
0 > = 0 (true) // unboxing
reference != secondReference (true)
mientras crea objetos, no una comparación primitiva. Entonces evalúa awhile(true) { // Never ending loop }
.fuente
Los objetos enteros son diferentes. Es diferente del tipo int básico.
Vea esta respuesta: ¿Cómo comparar correctamente dos enteros en Java?
La
i != j
parte es verdadera, que esperabas que fuera falsa.fuente
true
debido al autoboxing. En el caso del # 3, el autoboxing no se aplica y la comparación se realiza a nivel de objeto (ubicación de memoria).El ciclo no termina porque su condición es verdadera (i! = J es verdadera porque hay 2 objetos diferentes, use Integer.valueOf en su lugar) y dentro del ciclo los valores no cambian, por lo que su condición permanece verdadera para siempre.
fuente
Los objetos enteros son diferentes. Es diferente del tipo int básico. para que puedas hacer eso. lo que haces es simplemente comparar el objeto y, por supuesto, el resultado es verdadero.
fuente
Hay dos casos diferentes que tenemos que entender primero,
caso 1:
caso 2:
ambos son diferentes, como
en el caso 1:
i!=j
serátrue
porque ambos hacen referencia a dos objetos diferentes en el montón y no pueden ser iguales. Peroen el caso 2:
i==j
serátrue
porque ambos 10 son literales enteros y Java mantienepool for Integer literals
cuál tiene valor(-128 <= X <= 127)
. Entonces, en este caso 10 <= 127 resulta verdadero, por lo que ambos tendrán referencia al mismo objeto.fuente
Quizás la razón es que tanto 'i' como 'j' son objetos, y la comparación de objetos no es lo mismo que la comparación de referencias de objetos. Considere usar! I.equals (j) en lugar de i! = J
fuente
El programa sigue mostrando el mismo valor de
i
porque no está incrementando ni disminuyendo el valor dei
oj
. La condición en for siempre sigue evaluándose como verdadera, por lo que es un bucle infinito.fuente
i!=j
parte que sorprendentemente se evalúa como verdadera y no las<=
comparaciones.Las comparaciones <= y> = usarán el valor 0 sin caja, mientras que! = Comparará las referencias y tendrá éxito ya que son objetos diferentes.
Incluso esto también funciona i, e
pero esto no:
La razón es que Integer utiliza internamente el almacenamiento en caché para objetos Integer entre -128 y 127 y devuelve instancias de esa caché para el rango que cubre. No estoy seguro, pero supongo que también puede cambiar su valor máximo en el paquete "java.lang.Integer.IntegerCache.high".
Para una mejor comprensión, consulte la URL: https://www.owasp.org/index.php/Java_gotchas#Immutable_Objects_.2F_Wrapper_Class_Caching
fuente
debe saber que es un poco diferente en && this y this & cuando usa && luego, cuando la primera condición es verdadera, entonces verifica la segunda condición si es falsa, entonces no verificó la tercera condición porque en el operador & si una condición es falsa todos los declaración es falsa si usa || luego, si ve verdadero, devuelve verdadero en su código porque i y j son iguales, la primera y la segunda condición son verdaderas, luego en la tercera condición será falsa porque son iguales y la condición while es falsa.
fuente