首先来看下面一段代码:
public class Solution {
public static void main(String[] args) {
int i = 1;
i = i++;
int j = i++;
int k = i+ ++i*i++;
System.out.println("i=" + i + ",\tj="+j+",\tk="+k);
}
}
结果会是什么??
答案在文章末,你可以去看一下是否答对了
看一下这段代码反编译后的样子:
Compiled from "Solution.java"
public class com.example.Solution.Solution {
public com.example.Solution.Solution();
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: 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
24: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream;
27: iload_1
28: iload_2
29: iload_3
30: invokedynamic #3, 0 // InvokeDynamic #0:makeConcatWithConstants:(III)Ljava/lang/String;
35: invokevirtual #4 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
38: return
}
咱们来分析一下
int i = 1;
j = i++;
反编译后:
0: iconst_1
1: istore_1
2: iload_1
3: iinc 1, 1
6: istore_1
首先声明变量 i 并赋初值1,对应0和1行的反编译后的代码
j=i++
,Jvm会先处理等号右边的运算,先iload_1
,取出 i 的值为 1,并将 1 push到操作数栈中,再进行自加操作iinc 1, 1
,这个自加操作不需要使用操作数栈,所以直接是在变量 i 上加一,于是i=2,然后进行赋值操作,istore_1
将操作数栈中的 1 存到变量 i 上,i 的最终值又变回 1
再来分析
int j = i++;
反编译后:
7: iload_1
8: iinc 1, 1
11: istore_2
原理基本相同,先iload_1
,取出 i 的值为 1,并将 1 push到操作数栈中,再进行自加操作iinc 1, 1
,i=2,然后进行赋值操作,istore_2
将操作数栈中的 1 存到变量 j 上,j的值为 1 而不是 2
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
先iload_1
,取出 i 的值为 2,并将 2 push到操作数栈中,再进行自加操作iinc 1, 1
,i = 3,iload_1
,取出 i 的值为 3,并将 3 push到操作数栈中,再一次iload_1
,取出 i 的值为 3,并将 3 push到操作数栈中,然后进行自加操作iinc 1, 1
,i = 4,然后执行imul
操作,从操作数栈中弹出两个数3,3,3*3 得到9再压入到操作数栈中,然后执行iadd
操作,2+9得到11压入到操作数栈中,然后istore_3
将11赋给k
in a world
i++ 等价于 iload_1 + iinc 1,1先取变量值再变量加一
++等价于iinc 1,1 + iload_1先变量加一再取变量值
所以答案是:i=4, j=1, k=11