从底层分析Java中的i++和++i的区别
在JVM中,每一个Java方法的执行都是一个栈帧入栈出栈( 虚拟机栈)的过程。main方法也是一个栈帧。所有的计算操作(除了自增自减,在局部变量和表中进行)都需要到操作数栈中进行。计算结束之后,再把结果出栈放进局部变量表,或者直接传给下一个方法。即运算是在操作数栈中进行的。
i++:执行计算之前先将变量值压栈,然后在局部变量表中由i本身执行+1操作,之后将1压栈,最后将操作数栈中的值赋值给i(所以此时i的值为1)
* i++ 先赋值在运算,例如 a=i++,先赋值a=i,后运算i=i+1,所以结果是a==1
jvm底层理解为:先将i的值压栈,在在局部变量表中执行i+1操作(此时局部变量表中的i为1,但是操作数栈中 的i为0)
* ++i 先运算在赋值,例如 a=++i,先运算i=i+1,后赋值a=i,所以结果是a==2
jvm底层理解为:先在局部变量表中执行i+1操作,在将结果1压栈
int i = 0;
i++;
System.out.println(i);
字节码如下:
public static void main(java.lang.String[]);
descriptor: ([Ljava/lang/String;)V
flags: ACC_PUBLIC, ACC_STATIC
Code:
stack=2, locals=2, args_size=1
0: iconst_0 //将常量0压栈
1: istore_1 //从栈顶取出元素0,赋值给变量
2: iinc 1, 1 //局部变量+1
5: getstatic #2 //sout输出
8: iload_1 //压栈,将新值1放到栈顶,等待传递给下一个需要使用的方法
9: invokevirtual #3 // Method java/io/PrintStream.println:(I)V
12: return
int j = 0;
j = j++;
System.out.println(j);
public static void main(java.lang.String[]);
descriptor: ([Ljava/lang/String;)V
flags: ACC_PUBLIC, ACC_STATIC
Code:
stack=2, locals=2, args_size=1
0: iconst_0 //将常量0压栈
1: istore_1 //从栈顶取出元素0,赋值给变量
2: iload_1 //将变量0压到栈顶,为计算做准备
3: iinc 1, 1 //局部变量+1
6: istore_1 //计算结果出栈,赋值给i,因为i++先入栈后计算,导致1被0覆盖
7: getstatic #2 // sout打印
10: iload_1 //将变量0压到栈顶,等待传递给下一个需要使用的方法
11: invokevirtual #3 // Method java/io/PrintStream.println:(I)V
14: return
++i
int n = 0;
++n;
System.out.println(n);
public static void main(java.lang.String[]);
descriptor: ([Ljava/lang/String;)V
flags: ACC_PUBLIC, ACC_STATIC
Code:
stack=2, locals=2, args_size=1
0: iconst_0 //将常量0压栈
1: istore_1 //从栈顶取出元素0,赋值给变量
2: iinc 1, 1 //局部变量+1
5: getstatic #2 //sout输出
8: iload_1 //压栈,将新值放到栈顶,等待传递给下一个需要使用的方法
9: invokevirtual #3 // Method java/io/PrintStream.println:(I)V
12: return
//n = ++n 和 n++ 的结果一样吗? 一样的
public static void main(java.lang.String[]);
descriptor: ([Ljava/lang/String;)V
flags: ACC_PUBLIC, ACC_STATIC
Code:
stack=2, locals=2, args_size=1
0: iconst_0 //将常量0压栈
1: istore_1 //从栈顶取出元素0,赋值给变量
2: iinc 1, 1 //局部变量+1
5: iload_1 //将1压栈,为计算做准备
6: istore_1 //计算结果出栈,赋值给n
7: getstatic #2 //sout输出
10: iload_1 //压栈,将变量值放到栈顶,等待传递给下一个需要使用的方法
11: invokevirtual #3 // Method java/io/PrintStream.println:(I)V
14: return