Zuweisen einer Variablen, was tatsächlich passiert, Java

8

Was passiert im folgenden Beispiel eigentlich?

%Vor%

Die Ausgabe ist 3, aber ich wollte wissen, was tatsächlich unter den Abdeckungen passiert. Zum Beispiel weiß ich, dass runde Klammern eine höhere Priorität haben als + , was zuerst passiert (a = 2). Der Ausdruck sollte a = 2 + 2 werden. Zur Laufzeit sollte zuerst der Ausdruck in Klammern ausgeführt werden und dann wird a zu 2. Es scheint, dass das erste a auf der linken Seite zu + vor (a = 2) "geladen" wird und dieser letzte Ausdruck scheint das nicht zu überschreiben vorheriges Laden Mit anderen Worten, ich bin ziemlich verwirrt, was genau hinter den Kulissen passiert.

Wenn jemand weiß, vielen Dank im Voraus.

    
Rollerball 08.03.2013, 21:09
quelle

3 Antworten

2

Siehe das referenzierte Beispiel 15.7.1-2 von Ссылка , das ist fast identisch mit dem von Ihnen angegebenen Beispiel. Insbesondere:

  

Wenn der Operator ein Verbindungszuweisungsoperator ist (§15.26.2), dann   Auswertung des linken Operanden beinhaltet das Erinnern an den   Variable, die der linke Operand angibt und holen und speichern   Der Wert dieser Variablen für die implizite binäre Operation.

Wegen dieser Priorität wird die linke Hand von + = zuerst ausgewertet.

Es kann für Sie aufgrund der Klammern verwirrend sein, beachten Sie jedoch den Abschnitt zur Auswertung der Klammern: Ссылка , und insbesondere:

  

Die Programmiersprache Java respektiert die Reihenfolge der Auswertung   explizit durch Klammern und implizit durch den Operator angegeben   Vorrang.

In diesem Fall gibt die durch den Operator + = angegebene implizite Priorität an, dass der linke Operand gemäß der Spezifikation gespeichert wird. Während es zutrifft, dass Zuweisungsoperatoren, einschließlich "+=", die niedrigste Priorität haben, gibt die Spezifikation für + = an, dass der linke Operand gemäß 15.26.2 gespeichert wird.

    
Kirby 08.03.2013, 21:21
quelle
4

Aus dem JLS Abschnitt §15.26.2 Compound Assignment Operators :

  

Ein zusammengesetzter Zuordnungsausdruck der Form E1 op = E2 ist äquivalent   zu E1 = (T) ((E1) op (E2)), wobei T der Typ von E1 ist, außer dass E1   wird nur einmal ausgewertet.

Also für Ihr Beispiel haben wir:

%Vor%

Mit dem Ausdruck von links nach rechts ausgewertet. Daher die Ausgabe von 3

    
Rich O'Kelly 08.03.2013 21:12
quelle
2

Schauen wir uns den Bytecode des folgenden Programms an:

%Vor%

Wir müssen nur diesen Befehl ausführen:

%Vor%

um den folgenden Bytecode zu erhalten:

%Vor%

Erläuterung:

Wir konzentrieren uns nur auf die zwei Zeilen innerhalb der Hauptmethode:

%Vor%

[ int a = 1; beginnt hier]

%Vor%
  • Gibt int 1 auf den Stapel.
%Vor% %Vor%
  • Gibt den int-Wert vom Stapel in variable 1 ( variable 1 steht für a )
%Vor%

[ int a = 1; endet hier]

[ a += (a = 2); beginnt hier]

%Vor%
  • Lädt einen int Wert von local variable 1 und schiebt ihn auf den Stack.
%Vor% %Vor%
  • Gibt int 2 auf den Stapel.
%Vor% %Vor%
  • Dupliziere den Wert oben auf dem Stapel.
%Vor% %Vor%
  • Gibt den int-Wert vom Stapel nach variable 1 .
  • aus
%Vor% %Vor%
  • Fügt die beiden oberen Werte zusammen.
%Vor% %Vor%
  • Gibt den int-Wert vom Stapel nach variable 1 .
  • aus
%Vor%

[ a += (a = 2); endet hier]

%Vor%
  • Die Hauptmethode gibt zurück.

Fazit:

a = a + (a = 2) wird über mehrere Operationen ausgeführt. 2: iload_1 wird als erster Befehl von a += (a = 2); ausgeführt, der den ersten Operanden der Gleichung a = a + (a = 2) liest und auf den Stack drückt.

Als nächstes werden 3: iconst_2 und 4: dup ausgeführt, die im Prinzip 2 zweimal auf den Stapel schieben; eine für das Laden in a und die andere als zweiter Operand. Danach wird 5: istore_1 ausgeführt, welches 2 in a ( a = 2 ) lädt.

Schließlich werden 6: iadd und 7: istore_1 ausgeführt, wobei 6: iadd den ersten und den zweiten Operanden hinzufügt und das Ergebnis auf den Stapel verschiebt, und 7: istore_1 öffnet das Ergebnis und lädt es in a .

Der Einfachheit halber lassen Sie uns einen kurzen Blick auf diesen Code werfen:

%Vor%

und hier ist der Bytecode:

%Vor%

Wie Sie sehen können, macht es einfach folgendes:

  • Lädt int 1 in a .
  • Lädt int 3 in b .
  • Schiebt a und dann b auf den Stapel.
  • Führt die Addition für sie durch und schiebt das Ergebnis auf den Stapel.
  • Nimmt das Ergebnis vom Stapel und speichert es in a .
Eng.Fouad 08.03.2013 22:42
quelle