In Java verstehe ich, dass die Zuweisung den Wert des richtigen Operanden ergibt, also Anweisungen wie x == (y = x)
evaluieren true
.
Dieser Code wird jedoch ausgegeben false
.
public static void main(String[]args){
String x = "hello";
String y = "goodbye";
System.out.println(x.equals(x = y));
}
Warum ist das? Nach meinem Verständnis wird zuerst ausgewertet (x = y)
, der x
den Wert von zuweist y
, und dann der Wert von zurückgegeben y
. Dann x.equals(y)
wird ausgewertet, was true
da sein sollte x
und y
jetzt die gleichen Referenzen teilen soll, aber stattdessen bekomme ich false
.
Was passiert hier?
x.equals( y = x )
x
undy
?x = y
auf der rechten Seite ausgeführt wird , bevor diex
auf der linken Seite bewertet wird?x == (y = x)
als wahr bewertet wird. Das Verhalten dessen, was Sie vorschlagen, wäre dann offensichtlich ...Antworten:
Zuallererst: Das ist eine interessante Frage, sollte aber niemals in "echtem Code" auftauchen, da die Zuweisung zu der Variablen, die Sie in derselben Zeile aufrufen, verwirrend ist, selbst wenn Sie wissen, wie sie funktioniert.
Was hier passiert, sind diese 3 Schritte:
x
, dies führt zu einem Verweis auf die Zeichenfolge "Hallo").x = y
, was sich ändertx
, um auf die Zeichenfolge "Auf Wiedersehen" zu zeigen und auch einen Verweis auf diese Zeichenfolge zurückzugeben).equals
für das Ergebnis von # 1 auf und verwenden Sie das Ergebnis von # 2 als Parameter (der auf die Zeichenfolgen "Hallo" bzw. "Auf Wiedersehen" verweist).Ein Blick auf den für diese Methode erstellten Bytecode macht deutlich (vorausgesetzt, Sie sprechen fließend Java-Bytecode):
0: ldc #2 // String hello 2: astore_1 3: ldc #3 // String goodbye 5: astore_2 6: getstatic #4 // Field java/lang/System.out:Ljava/io/PrintStream; 9: aload_1 10: aload_2 11: dup 12: astore_1 13: invokevirtual #5 // Method java/lang/String.equals:(Ljava/lang/Object;)Z 16: invokevirtual #6 // Method java/io/PrintStream.println:(Z)V 19: return
Zeile 9 ist Schritt 1 oben (dh wertet
x
den Wert aus und merkt sich ihn).Zeile 10-12 ist Schritt 2. Sie wird geladen
y
, dupliziert (einmal zum Zuweisen, einmal für den Rückgabewert des Zuweisungsausdrucks) und zugewiesenx
.Zeile 13 ruft
equals
das in Zeile 9 berechnete Ergebnis und das Ergebnis der Zeilen 10-12 auf.quelle
x.equals(x = y)
=>"hello".equals(x = y)
=>"hello".equals(x = "goodbye")
=>"hello".equals("goodbye")
=>false
..
eine höhere Priorität hat als=
.Gute Frage! Und die JLS hat die Antwort ...
§15.12.4.1 (Beispiel 15.12.4.1-2). Auswertungsreihenfolge während des Methodenaufrufs:
Also, in:
String x = "hello"; String y = "goodbye"; System.out.println(x.equals(x = y));
Das Auftreten von
x
before.equals
wird zuerst vor dem Argumentausdruck ausgewertetx = y
.Daher wird ein Verweis auf die Zeichenfolge
hello
als Zielreferenz gespeichert, bevor die lokale Variablex
geändert wird, um auf die Zeichenfolge zu verweisengoodbye
. Infolgedessen wird dieequals
Methode für das Zielobjekthello
mit Argument aufgerufengoodbye
, sodass das Ergebnis des Aufrufs lautetfalse
.quelle
Es ist wichtig, sich daran zu erinnern, dass ein
String
in Java ein Objekt und daher eine Referenz ist. Wenn du anrufstEs wird überprüft , ob der Wert an der Stelle verwiesen werden derzeit von
x
gleich , was Sie vorbei in. Im Innern Sie den Wert ändern, derx
wird Referenzierung , aber Sie sind immer noch telefonierenequals
mit der ursprünglichen Referenz (der Verweis auf „Hallo“). Im Moment wird Ihr Code also verglichen, um festzustellen, ob "Hallo" gleich "Auf Wiedersehen" ist, was eindeutig nicht der Fall ist. Wenn Sie nach diesem Punktx
erneut verwenden, wird auf denselben Wert wie y verwiesen.quelle
"hello".equals((x = y))
zurückkehrentrue
?x=y
in der Klammer bedeutet, dass der Ausdruck(x=y)
jetzt istgoodbye
, während das äußere x inx.equals
den Wert enthälthello
quelle
Reimus gab die richtige Antwort, aber ich würde gerne näher darauf eingehen.
In Java (und den meisten Sprachen) ist die Konvention variabel links und die Zuweisung rechts.
Lassen Sie es uns zusammenfassen:
String x = "hello"; //x <- "hello" String y = "goodbye"; //y <- "goodbye";
Für Debugging-Zwecke sowie zur Lesbarkeit des Codes ist es immer eine gute Praxis, Ihre Zeilen so aufzuteilen, dass sie nur eines tun.
System.out.println(x.equals(x = y)); //Compound statement
Hier
x.equals(...)
wird auf die ursprüngliche Referenz zu x oder "Hallo" aufgerufen, es wird für die zweite Referenz aktualisiert.Ich würde dies schreiben als (und dies wird Ihnen Ihre erwartete Antwort geben):
x = y; // x <- y = "goodbye" boolean xEqualsX = x.equals(x); // xEqualsX <- true System.out.println(xEqualsX); // "true"
Nun scheint es offensichtlich, dass es sich so verhalten sollte, aber es ist auch sehr einfach, genau zu sehen, was in jeder Zeile vor sich geht, was Sie anstreben sollten.
quelle
System.out.println("Bytes: "+1024*k);
Aussage : Würden Sie empfehlen, dass drei Aussagen geschrieben werden?Ich habe Ihre Frage in Eclipse versucht, Ihre beiden Ausdrücke sind korrekt. 1) x == (y = x) als wahr auswerten, es ist wahr, weil der Wert von x y zuweist, was 'Hallo' ist, dann werden x und y verglichen, sie werden gleich sein, so dass das Ergebnis wahr ist
2) x.equal (x = y) ist falsch, weil der Wert von y x zugewiesen wird, was auf Wiedersehen ist, dann sind x und x, die ihren Wert vergleichen, unterschiedlich, so dass das Ergebnis falsch ist
quelle
Ich sehe die Frage in Laienbegriffen als
"hello".equals("goodbye")
. Es wird also false zurückgegeben.quelle
In Java ist String eine Klasse.
String x = "hello"; String y = "goodbye";
ist eine zwei verschiedene Zeichenfolge, die sich auf zwei verschiedene Werte bezieht, die nicht gleich sind und wenn Sie vergleichen
System.out.println(x.equals(x = y)); //this compare value (hello and goodbye) return true System.out.println(x == (y = x)); // this compare reference of an object (x and y) return false
quelle
System.out.println(x.equals(x = y));
wird im Gegensatz zu Ihrer Antwort false zurückgegeben.Es wird angezeigt, ob x.equals (y y zuweisen, immer true zurückgeben), also im Grunde x.equals (true)
quelle