Rzućmy okiem na kod bajtowy następującego programu:
package A;
public class Test
{
public static void main(String[] args)
{
int a = 1;
a += (a = 2);
}
}
Po prostu trzeba uruchomić polecenie:
javap -c Test.class
aby uzyskać następujące kodu bajtowego:
public class A.Test {
public A.Test();
Code:
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: return
public static void main(java.lang.String[]);
Code:
0: iconst_1
1: istore_1
2: iload_1
3: iconst_2
4: dup
5: istore_1
6: iadd
7: istore_1
8: return
}
Objaśnienie:
Będziemy po prostu skupić się na dwóch liniach wewnątrz główne metody:
int a = 1;
a += (a = 2);
[int a = 1;
zaczyna tutaj]
0: iconst_1
- nawiewy int
1
na stosie .
-------------
| |
-------------
| |
-------------
| 1 |
-------------
STACK
1: istore_1
- tato Int wartość od stosu
variable 1
(variable 1
oznacza a
)
-------------
| | variable 1
------------- --------------
| | | 1 |
------------- --------------
| |
-------------
STACK
[int a = 1;
wykończenia tutaj]
[a += (a = 2);
zaczyna tutaj]
2: iload_1
- wczytuje wartość int z lokalnego
variable 1
i wypycha go na stosie.
-------------
| | variable 1
------------- --------------
| | | |
------------- --------------
| 1 |
-------------
STACK
3: iconst_2
-------------
| | variable 1
------------- --------------
| 2 | | |
------------- --------------
| 1 |
-------------
STACK
4: dup
- powielać wartość na górze stosu.
-------------
| 2 | variable 1
------------- --------------
| 2 | | |
------------- --------------
| 1 |
-------------
STACK
5: istore_1
- Pops int wartość ze stosu do
variable 1
.
-------------
| | variable 1
------------- --------------
| 2 | | 2 |
------------- --------------
| 1 |
-------------
STACK
6: iadd
- Dodaje dwie górne wartości razem.
-------------
| | variable 1
------------- --------------
| | | 2 |
------------- --------------
| 3 |
-------------
STACK
7: istore_1
- Pops int wartość ze stosu do
variable 1
.
-------------
| | variable 1
------------- --------------
| | | 3 |
------------- --------------
| |
-------------
STACK
[a += (a = 2);
wykończenia tutaj]
8: return
Wniosek:
a = a + (a = 2)
odbywa się za pomocą kilku operacji. 2: iload_1
jest wykonywane jako pierwsze polecenie a += (a = 2);
, które odczytuje pierwszy operand równania a = a + (a = 2)
i przesuwa na stos.
Następnie wykonywane są 3: iconst_2
i 4: dup
, które w zasadzie wypychają dwa razy int 2
na stos; jeden do załadowania go do a
, a drugi jako drugi operand. Następnie wykonywany jest 5: istore_1
, który ładuje 2
do a
(a = 2
).
Wreszcie 6: iadd
i 7: istore_1
są wykonywane gdzie 6: iadd
Dodaje pierwszy operand i drugiego argumentu i odkłada wynik na stos, a 7: istore_1
wyskakuje wynik i ładuje go do a
.
Dla uproszczenia załóżmy rzucić okiem na ten kod:
int a = 1;
int b = 3;
a += b;
i tu jest jego kod bajtowy:
public class A.Test {
public A.Test();
Code:
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: return
public static void main(java.lang.String[]);
Code:
0: iconst_1
1: istore_1
2: iconst_3
3: istore_2
4: iload_1
5: iload_2
6: iadd
7: istore_1
8: return
}
Jak widać, po prostu wykonuje następujące czynności:
- Obciążenia int
1
do a
.
- Ładuje int
3
w b
.
- Przesuwa
a
następnie b
na stos.
- Wykonuje dodawanie na nich i przesuwa wynik na stos.
- Wyrzuca wynik ze stosu i zapisuje go w postaci
a
.
pokrewne: http://stackoverflow.com/questions/11324850/why-swapping-integer-variable-by-xor-doesnt-work-in-a-single-line/11325458 – nhahtdh
samo co 'int a = 1; int tmpvar = (a = 2); a + = tmpvar; ' –
Przekłada się na' a = a + (a = 2); ', a operandy są oceniane od lewej do prawej. –