J'ai écrit un morceau de code Java qui s'exécute dans une boucle infinie.
Voici le code:
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);
}
}
}
Dans le code ci-dessus, tout en voyant la condition dans la while
boucle, il semble au début que ce programme n'ira pas à l'intérieur de la while
boucle. Mais en fait, c'est une boucle infinie et continue à imprimer la valeur.
Que se passe-t-il ici?
i<=j && j<=i && i!=j
cette condition est toujours évaluée comme vraie. Il suffit de prendre un morceau de papier et d'évaluer, vous l'attraperez :)i
ouj
, quand vous attendez-vous à ce que la boucle se termine?i<=j
etj<=i
vous pouvez conclure, celai == j
, ce qui contredit le dernier terme. Ainsi, l'expression entière est évaluée à false et le while ne serait pas entré. Le point clé est l'identité de l'objet ici!Réponses:
i <= j
est évaluée àtrue
, parce que unboxing automatique se produit pour des comparaisons int, puis à la foisi
etj
maintenir la valeur par défaut,0
.j <= i
est évalué entrue
raison de la raison ci-dessus.i != j
est évalué àtrue
, car les deuxi
etj
sont des objets différents. Et tout en comparant des objets, il n'est pas nécessaire de déballer automatiquement.Toutes les conditions sont vraies, et vous ne changez pas
i
etj
en boucle, donc il fonctionne à l'infini.la source
Integer.valueOf(0) == Integer.valueOf(0)
est toujours évalué à vrai car dans ce cas, le même objet est renvoyé (voir IntegerCache grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/… )Parce que vous comparez
0 < = 0 (true) // unboxing
0 > = 0 (true) // unboxing
reference != secondReference (true)
comme vous créez des objets, pas une comparaison primitive. Donc, il évaluewhile(true) { // Never ending loop }
.la source
Les objets entiers sont différents. Il est différent du type int de base.
Voir cette réponse: Comment comparer correctement deux nombres entiers en Java?
La
i != j
partie est vraie, ce que vous vous attendiez à être faux.la source
true
raison de la détection automatique. Dans le cas du n ° 3, l'autoboxing ne s'applique pas et la comparaison a lieu au niveau de l'objet (emplacement mémoire).La boucle ne se termine pas car votre condition est vraie (i! = J est vraie car il y a 2 objets différents, utilisez plutôt Integer.valueOf) et à l'intérieur de la boucle les valeurs ne changent pas, donc votre condition reste vraie pour toujours.
la source
Les objets entiers sont différents. Il est différent du type int de base. donc vous pouvez faire comme ça. ce que vous faites, c'est simplement comparer l'objet et bien sûr le résultat est vrai.
la source
Il y a deux cas différents que nous devons d'abord comprendre,
cas 1:
cas 2:
les deux sont différents, car
dans le cas 1:
i!=j
seratrue
parce que les deux font référence à deux objets différents dans le tas et ne peuvent pas être identiques. Maisdans le cas 2:
i==j
seratrue
parce que les deux 10 sont des littéraux entiers et Java maintientpool for Integer literals
qui ont une valeur(-128 <= X <= 127)
. Donc, dans ce cas, 10 <= 127 résultats vrais, donc les deux auront référence au même objet.la source
La raison en est peut-être que «i» et «j» sont des objets et que la comparaison d'objets n'est pas la même chose que la comparaison de références d'objets. Veuillez envisager d'utiliser! I.equals (j) au lieu de i! = J
la source
Le programme continue d'afficher la même valeur de
i
parce que vous n'incrémentez ni ne décrémentez la valeur dei
ouj
. La condition dans for continue à être évaluée à true, il s'agit donc d'une boucle infinie.la source
i!=j
partie qui est étonnamment vraie et non sur les<=
comparaisons.Les comparaisons <= et> = utiliseront la valeur sans boîte 0, tandis que le! = Comparera les références et réussira car ce sont des objets différents.
Même cela fonctionnera aussi i, e
mais cela ne fonctionne pas:
La raison en est que Integer utilise en interne la mise en cache pour les objets Integer entre -128 et 127 et renvoie les instances de ce cache pour la plage qu'il couvre. Je ne suis pas sûr mais je suppose que vous pouvez également modifier sa valeur maximale dans le package "java.lang.Integer.IntegerCache.high".
Pour une meilleure compréhension, vérifiez l'URL: https://www.owasp.org/index.php/Java_gotchas#Immutable_Objects_.2F_Wrapper_Class_Caching
la source
vous devez savoir que c'est un peu différent dans && ceci et ceci & quand vous utilisez && alors quand la première condition est vraie alors il vérifie la deuxième condition si c'est faux alors il n'a pas vérifié la troisième condition parce que dans l'opérateur & si une condition est fausse tout le la déclaration est fausse si utiliser || alors s'il voit vrai alors il retourne vrai dans votre code parce que i et j sont égaux, la première et la deuxième condition sont vraies alors dans la troisième condition, elles seront fausses parce qu'elles sont égales et tandis que la condition est fausse.
la source