通常我们认为:
++a表示取a的地址,然后增加它的内容,然后把值放在寄存器中;
a++表示取a的地址,把它装入寄存器中,然后增加内存中a的值;
比如:
但是,如果a= a++;?还会是我们平日认为的那种结果吗?
比如:
public class VarDemo {
public static void main(String[] args) {
int a =3;
a = a++;
a = a++;
System.out.println("a的值为:"+a);
}
是不是很意外?下面我们使用反汇编命令进行分析编译器内部流程:
1.
将常量3压入数据栈
2.
弹出操作数栈顶的数(此时为 3)并赋值给局部变量第一个元素即索引为 1 的 a;
3.
表示把局部变量索引为 1 的变量(这里是 a)压入操作数栈,此时栈顶元素为 3 。
4.
把局部变量索引为 1 的数加 1 ,此时 a 的值为 4。特别注意:这个4没有压入操作数栈。
5.
弹出操作数栈顶的数(此时为 3)并赋值给局部变量第一个元素即索引为 1 的 a;注意此时变量a的值由4变为3;
6.
把局部变量索引为 1 的变量(这里是 a)压入操作数栈,注意此时栈顶元素为 3 。
7.
把局部变量索引为 1 的数加 1 ,此时 a 的值再次变为 4。注意:这个结果没有压入操作数栈,数据栈中依然是3.
8.
弹出操作数栈顶的数(此时为 3)并赋值给局部变量第一个元素即索引为 1 的 a;注意此时变量a的值由4变为3;
经过以上8个步骤,就不难看出为什么a=a++;结果为3.
下面思考类似的操作:
public class VarDemo {
public static void main(String[] args) {
int a =3;
a = ++a;
System.out.println("a的值为:"+a);
}
}
在这里需要特别注意 iinc 和 iload_1 这两个命令的执行顺序,这是影响结果关键因素.