先来看一段代码。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
| public static void main(String[] args) {
int i = 5;
int a = i++;
System.out.println("a=" + a);
System.out.println(i);
int b = i--;
System.out.println("b=" + b);
System.out.println(i);
int c = --i;
System.out.println("c=" + c);】
System.out.println(i);
int d = ++i;
System.out.println("d=" + d);
System.out.println(i);
}
|
这段代码的输出结果可能很多人都能看出来,如下所示
1
2
3
4
5
6
7
8
9
| a=5
6
b=6
5
c=4
4
d=5
5
k==5
|
其中的计算逻辑也很清晰,i++
是先赋值后计算,而++i
是先计算后赋值。
那么换一种写法呢,可能很多小伙伴都会猜错。
1
2
3
4
5
6
7
8
9
10
11
| public static void main(String[] args) {
int i = 5;
i = i++;
System.out.println(i);
i = i--;
System.out.println(i);
i = --i;
System.out.println(i);
i = ++i;
System.out.println(i);
}
|
这段代码按照之前的逻辑来看,输出结果应该为6,5,4,5。但是执行程序后的输出结果为
为了搞清楚这中间的逻辑,我们不妨使用javap -c
编译一下源代码看看
1
2
3
4
5
| public static void main(String[] args) {
int i = 5;
i = i++;
System.out.println(i);
}
|
编译后的代码如下:
1
2
3
4
5
6
7
8
9
10
11
| public static void main(java.lang.String[]);
Code:
0: iconst_5
1: istore_1
2: iload_1
3: iinc 1, 1
6: istore_1
7: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream;
10: iload_1
11: invokevirtual #3 // Method java/io/PrintStream.println:(I)V
14: return
|
这其中用到的指令集的含义如下:
*iconst*
:将单字节的int常量值(-128~127)推送至栈顶istore
:将栈顶int型数值存入指定本地变量iload
:将指定的int型本地变量推送至栈顶***iinc***
:该指令用于对本地(局部)变量进行自增减操作。该指令第一参数为本地变量的编号,第二个参数为自增减的数量getstatic
:获取指定类的静态域,并将其值压入栈顶
所以这段代码的指令集的含义为:
iconst_5
表示将一个值为5的int值推送到栈顶istore_1
把栈顶的int值5赋给第二个本地变量i
(第1个本地变量应该是this)iload_1
表示把第二个本地变量i
的值推入栈顶,此时栈顶仍然为5iinc 1, 1
表示将第二个本地变量的值加1,也就是执行了i++
,此时的i
值为6了已经istore_1
再次将栈顶int值(仍然为5)赋给第二个本地变量i
getstatic
后面为输出的代码
因此最终打印出来的结果是5。