關於java中前置++和后置++


一般認為前置++是先將變量的值加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) {
                break;
            }
            System.out.println(k);
        }
    }
}

猜猜結果是什么?

實際上,不管是前置++,還是后置++,都是先將變量的值加1,然后才繼續計算的。二者之間真正的區別是:前置++是將變量的值加1后,使用增值后的變量進行運算的,而后置++是首先將變量賦值給一個臨時變量,接下來對變量的值加1,然后使用那個臨時變量進行運算。

對於如下代碼片段(前置++):

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

實際第二句上相當於:

i+=1; //將i加1
j=i*5; //將加1后的值與之進行計算, 此結果為:10

而對於如下代碼片段(后置++):

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

第二句上相當於:

int temp=i;  // 將i賦值給一個臨時變量
i+=1;        //將i加1
j=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中第二個 加1
10          7: istore_1 //從操作數頂保存至local var,覆蓋了以前的 11          8: getstatic     #16                 // Field java/lang/System.out:Ljava/io/PrintStream;
12         11: iload_1   //加載的參數為棧中的第二個,即仍然為100
13         12: invokevirtual #22                 // Method java/io/PrintStream.println:(I)V
14         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 是方法參數,一般方法(實例方法,除了static、final以及private修飾外的)第一個local var 是this)
 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; //55
15     }
16 
17     public static void main(String[] args) {
18         System.out.println(proPlus());//56
19         System.out.println(postPlus());//55
20 
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: ireturn     //返回棧頂的int類型的量
static 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)前,先將變量的值壓入棧,執行增值指令后,使用的是之前壓入棧的值。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM