先看代码
int i = 1;
i = i++;
int j = i++;
int k = i + ++i * i++;
System.out.println("i: "+i);
System.out.println("j: "+j);
System.out.println("k: "+k);
输出:
i: 4
j: 1
k: 11
原因是java 编译操作
编译源码:
编译类 -> javap -v 类名.class
stack=3, locals=4, args_size=1
0: iconst_1
1: istore_1
2: iload_1
3: iinc 1, 1
6: istore_1
7: iload_1
8: iinc 1, 1
11: istore_2
12: iload_1
13: iinc 1, 1
16: iload_1
17: iload_1
18: iinc 1, 1
21: imul
22: iadd
23: istore_3
在这里 0 1 -> int i=1
2 3 6 i = i++
7 8 11 j = i++
16 - 23 int k = i + ++i * i++;
分析编译文件
1.操作数栈是FILO 指令里
- iinc 只在局部变量表里执行,剩下的都在操作数栈执行。
所以在 2: iload_1 取局部变量表 序号1的值
局部变量表 操作数栈
1(序号) i =1 1
然后 3: iinc i++,只在局部变量表执行,不在操作数栈执行
局部变量表 操作数栈
1(序号) i =2 1
然后 6: istore_1,istore_1 把操作数栈值赋给局部变量表下标为1的元素
局部变量表 操作数栈
1(序号) i =1 空
所以 i = i ++ 执行完 i的值是1
然后看 j = i++
7: iload_1 获取局部变量表 序号1的值
局部变量表 操作数栈
1(序号) i =1 1
2(序号) j = 空
然后又执行i++ 8: iinc 只在局部变量表操作
局部变量表 操作数栈
1(序号) i =2 1
2(序号) j = 空
然后关键的来了 11: istore_2 操作数栈把值给了局部变量表编号2
局部变量表 操作数栈
1(序号) i =2 1
2(序号) j = 1 空
所以这条语句结束后 i变成2 j值为1
然后看第三句话
int k = i + ++i * i++;
12: iload_1
13: iinc 1, 1
16: iload_1
17: iload_1
18: iinc 1, 1
21: imul
22: iadd
23: istore_3
局部变量表 操作数栈
1(序号) i =2 空
2(序号) j = 1 空
3(序号) k = 空 空
首先取出 i 12: iload_1
局部变量表 操作数栈
1(序号) i =2 2
2(序号) j = 1 空
3(序号) k = 空 空
执行 ++i 部分
局部变量表 操作数栈
1(序号) i =3 2
2(序号) j = 1 空
3(序号) k = 空 空
然后读取i,在执行 i++ 部分
16: iload_1
17: iload_1
18: iinc 1, 1
注意这里读取了两次 就是 ++i 和 i++部分
局部变量表 操作数栈
1(序号) i =4 2
2(序号) j = 1 3
3(序号) k = 空 3
然后执行乘法和加法
21: imul
22: iadd
对操作数栈的值进行计算 3*3 +2
局部变量表 操作数栈
1(序号) i =4 空
2(序号) j = 1 空
3(序号) k = 11 空
所以最后输出
i: 4
j: 1
k: 11
类比:
int i=1;
i = i++;
System.out.println(i); -> 1 先进栈后自增
int i =1;
i = ++ i;
System.out.println(i) -> 2 先自增后进栈
int i=1,j=1;
j = i ++;
System.out.println(i); -> 2 操作数栈FILO