Ich habe einen Java-Code geschrieben, der in einer Endlosschleife ausgeführt wird.
Unten ist der 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);
}
}
}
Im obigen Code while
sieht es zunächst so aus, als würde das Programm nicht in die Schleife gelangen , obwohl die Bedingung in der Schleife while
angezeigt wird. Aber eigentlich ist es eine Endlosschleife und druckt den Wert weiter.
Was passiert hier?
i<=j && j<=i && i!=j
diese Bedingung immer als wahr ausgewertet wird. Nehmen Sie einfach ein Stück Papier und bewerten Sie, ob Sie es fangen werden :)i
oderj
wann würden Sie erwarten, dass die Schleife endet?i<=j
undj<=i
Sie können feststellen, dassi == j
, was den letzten Begriff widerspricht. Somit wird der gesamte Ausdruck als falsch ausgewertet und die Weile würde nicht eingegeben. Entscheidend ist hier die Objektidentität!Antworten:
i <= j
wird ausgewertettrue
, da das automatische Entpacken für int-Vergleiche und dann für beide erfolgti
undj
der Standardwert beibehalten wird0
.j <= i
wirdtrue
aus dem oben genannten Grund ausgewertet .i != j
wird ausgewertettrue
, weil beidei
undj
unterschiedliche Objekte sind. Beim Vergleichen von Objekten ist kein automatisches Entpacken erforderlich.Alle Bedingungen sind wahr, und Sie ändern sich nicht
i
und befinden sichj
in einer Schleife, sodass es unendlich läuft.quelle
Integer.valueOf(0) == Integer.valueOf(0)
immer als wahr ausgewertet wird, da in diesem Fall dasselbe Objekt zurückgegeben wird (siehe IntegerCache grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/… )Weil du vergleichst
0 < = 0 (true) // unboxing
0 > = 0 (true) // unboxing
reference != secondReference (true)
Während Sie Objekte erstellen, kein primitiver Vergleich. Also wertet es auswhile(true) { // Never ending loop }
.quelle
Die ganzzahligen Objekte sind unterschiedlich. Es unterscheidet sich vom grundlegenden int-Typ.
Siehe diese Antwort: Wie vergleiche ich zwei Ganzzahlen in Java richtig?
Der
i != j
Teil ist wahr, von dem Sie erwartet hatten, dass er falsch ist.quelle
true
aufgrund von Autoboxing ausgewertet . Im Fall von # 3 gilt kein Autoboxing und der Vergleich erfolgt auf Objektebene (Speicherort).Die Schleife endet nicht, weil Ihre Bedingung wahr ist (i! = J ist wahr, weil es 2 verschiedene Objekte gibt, verwenden Sie stattdessen Integer.valueOf) und innerhalb der Schleife ändern sich die Werte nicht, sodass Ihre Bedingung für immer wahr bleibt.
quelle
Die ganzzahligen Objekte sind unterschiedlich. Es unterscheidet sich vom grundlegenden int-Typ. so kannst du es einfach machen. Was Sie tun, ist nur das Objekt zu vergleichen und natürlich ist das Ergebnis wahr.
quelle
Es gibt zwei verschiedene Fälle, die wir zuerst verstehen müssen:
Fall 1:
Fall 2:
beide sind unterschiedlich, wie
in Fall 1:
i!=j
liegt daran,true
dass beide auf zwei verschiedene Objekte im Heap verweisen und nicht gleich sein können. Aberin Fall 2:
i==j
liegt daran,true
dass beide 10 ganzzahlige Literale sind und Java verwaltetpool for Integer literals
, die Wert haben(-128 <= X <= 127)
. In diesem Fall sind also 10 <= 127 wahr. Beide beziehen sich also auf dasselbe Objekt.quelle
Vielleicht liegt der Grund darin, dass sowohl 'i' als auch 'j' Objekte sind und der Objektvergleich nicht mit dem Objektreferenzvergleich identisch ist. Bitte verwenden Sie! I.equals (j) anstelle von i! = J.
quelle
Das Programm hält auf den gleichen Wert darstellen kann,
i
weil Sie nicht erhöht oder verringert entweder der Werti
oderj
. Die Bedingung im for wird immer als wahr ausgewertet, es handelt sich also um eine Endlosschleife.quelle
i!=j
Teil, der überraschenderweise als wahr bewertet wird, und nicht auf die<=
Vergleiche.Die Vergleiche <= und> = verwenden den unboxed-Wert 0, während! = Die Referenzen vergleicht und erfolgreich ist, da es sich um unterschiedliche Objekte handelt.
Auch das wird auch funktionieren, z
aber das geht nicht:
Der Grund dafür ist, dass Integer intern das Caching für Integer-Objekte zwischen -128 und 127 verwendet und Instanzen aus diesem Cache für den abgedeckten Bereich zurückgibt. Ich bin nicht sicher, aber ich denke, Sie können den Maximalwert auch im Paket "java.lang.Integer.IntegerCache.high" ändern.
Zum besseren Verständnis überprüfen Sie die URL: https://www.owasp.org/index.php/Java_gotchas#Immutable_Objects_.2F_Wrapper_Class_Caching
quelle
Sie müssen wissen, dass es in && this und this & etwas anders ist. Wenn Sie && verwenden, dann, wenn die erste Bedingung wahr ist, dann prüft es die zweite Bedingung, wenn es falsch ist, dann prüft es nicht die dritte Bedingung, weil in & operator, wenn eine Bedingung falsch ist, alle Anweisung ist falsch, wenn || verwendet wird Wenn es dann true sieht, gibt es in Ihrem Code true zurück, weil i und j gleich sind. Erste und zweite Bedingung sind wahr. In der dritten Bedingung ist es falsch, weil sie gleich sind und während Bedingung falsch ist.
quelle