首页 > 代码库 > 关于前置++和后置++

关于前置++和后置++

一般认为前置++是先将变量的值加1,然后使用加1后的值参与运算;而后置++是先使用该值参与运算,然后再将该值加1。

先看第一个例子:

package test;public class Plus_Test01 {    public static void main(String[] args) {        int i = 100;        i = i++;        System.out.println(i);    }}

猜猜结果是什么?

接着看第二个:

package test;public class Plus_Test02 {    public static void main(String[] args) {        int k = 100;        while (true) {            if (k++ > 100) {                // System.out.println(k);                break;            }            System.out.println(k);        }    }}

猜猜结果是什么?

实际上,不管是前置++,还是后置++,都是先将变量的值加1,然后才继续计算的。二者之间真正的区别是:前置++是将变量的值加1后,使用增值后的变量进行运算的,而后置++是首先将变量赋值给一个临时变量,接下来对变量的值加1,然后使用那个临时变量进行运算。

对于如下代码片段(前置++):

int i=1;int j=++i*5;

实际第二句上相当于:

i+=1; //将i加1j=i*5; //将加1后的值与之进行计算, 此结果为:10

而对于如下代码片段(后置++):

int i=1;int j=i++*5;

第二句上相当于:

int temp=i;  // 将i赋值给一个临时变量i+=1;        //将i加1j=temp*5;   //将临时变量与之计算, 此结果为:5

对于第一个例子,相当于:

int temp=i;i+=1;i=temp; //

所以结果应该为不变的,即100。

第一个例子的汇编代码为:

 1 public static void main(java.lang.String[]); 2     descriptor: ([Ljava/lang/String;)V 3     flags: ACC_PUBLIC, ACC_STATIC 4     Code: 5       stack=2, locals=2, args_size=1 6          0: bipush        100 7          2: istore_1 8          3: iload_1 9          4: iinc          1, 1  //local var中第二个 加110          7: istore_1             //保存至local var11          8: getstatic     #16                 // Field java/lang/System.out:Ljava/io/PrintStream;12         11: iload_1   //加载的参数为栈中的第二个,即仍然为10013         12: invokevirtual #22                 // Method java/io/PrintStream.println:(I)V14         15: return

对于第二个例子,其实不难,结果是101,注意看一下流程,以后不能在犯这样的错误了。(流程为:首先比较temp=i,temp>100,,显然不成立,将i+=1,跳到syso那一句,打印的当然是101,再次循环同样有temp=i,temp>100,这次是成立的,然后i+=1,直接跳出循环,不会执行while里面的语句)。

第二个例子的汇编(只选取了main方法):

 1 public static void main(java.lang.String[]); 2     descriptor: ([Ljava/lang/String;)V 3     flags: ACC_PUBLIC, ACC_STATIC 4     Code: 5       stack=2, locals=2, args_size=1 6          0: bipush        100       //100压栈 7          2: istore_1                  //保存至第二个local var(第一个local var 是方法参数) 8          3: iload_1                  //从第二个local var加载 9          4: iinc          1, 1       //给local var的2号位置的int值增加1(局部变量自增,结果仍然在local var中,操作数栈顶1不会变)10          7: bipush        100    //100压栈11          9: if_icmple     15  //比较操作数栈顶的两个int整型值,如果第一个小于或者等于第二个的话,然后跳转到15行12         12: goto          25   //否则跳转到25行(即操作数栈顶1>操作数栈顶2)13         15: getstatic     #2                  // Field java/lang/System.out:Ljava/io/PrintStream;14         18: iload_1   //  //从第一个个local var加载15         19: invokevirtual #3                  // Method java/io/PrintStream.println:(I)V  //调用该方法16         22: goto          3  //再次回跳至3,再次循环17         25: return  //退出

第三个例子:

技术分享
 1 package test; 2  3 public class Plus_Test03 { 4  5     static int proPlus() { 6         int i = 55; 7         int j = ++i; 8         return j; //56 9     }10 11     static int postPlus() {12         int i = 55;13         int j = i++;14         return j; //5515     }16 17     public static void main(String[] args) {18         System.out.println(proPlus());//5619         System.out.println(postPlus());//5520 21     }22 }
View Code

第三个例子的汇编:

static int proPlus();    descriptor: ()I    flags: ACC_STATIC    Code:      stack=1, locals=2, args_size=0         0: bipush        55   //55压栈         2: istore_0         //将int型栈顶的存储至第一个local var         3: iinc          0, 1  //第一个local var加1         6: iload_0         //从local var加载         7: istore_1       //保存至第二个local var         8: iload_1         //栈顶为第二个local var         9: ireturnstatic int postPlus();    descriptor: ()I    flags: ACC_STATIC    Code:      stack=1, locals=2, args_size=0         0: bipush        55           2: istore_0         3: iload_0             //加载至栈         4: iinc          0, 1   //第一个local var加1         7: istore_1         8: iload_1         9: ireturn

可见,前置++ 和后置++的不同点在于上面蓝色的部分,这两部分是反过来的。对于前置来说,会将local var中的数加1然后加载至栈中,而后置则是先从栈local var中加载至栈,然后将local var的加1,相当于留了一个备份。

结论:

一。前置、与后置++都是先将变量的值加1,而不是前置++先加1然后运算,而后置++先运算后加1。
二。从程序上说,后置++先将变量赋值给一个临时变量,然后将变量的值加1,接下来使用那个临时变量参与运算。
三。从指令上说,后置++在执行增值指令(iinc)前,先将变量的值压入栈,执行增值指令后,使用的是之前压入栈的值。

关于前置++和后置++