1. 程式人生 > >從位元組碼角度分析 i++ 和 ++i 實現

從位元組碼角度分析 i++ 和 ++i 實現

最近看到個面試題:


int j=0;
for(int i=0;i<100;i++)
    j = j++;
System.out.println(j);


輸出結果是0,如果換成j++,那麼輸出100,這是為什麼?


對於這種問題,其實有點經驗的程式設計師都知道,前置++和後置++的運算區別:

1、前置++是將自身加1的值賦值給新變數,同時自身也加1

2、後置++是將自身的值賦給新變數,然後才自身加1


話雖這麼說,那怎麼來證明上面兩點呢?

萬物皆有始有終,對於程式碼,只能從位元組碼的角度看看是不是能挖掘有價值的資訊。


在講位元組碼之前,先簡單的瞭解下Java棧,在JVM中有這麼一個數據結構叫Java棧,當執行緒啟動的時候,會分配一塊記憶體當做該執行緒的棧,每個棧由一系列的棧幀組成。每個棧幀對應一個方法,當執行緒執行方法時,就是棧幀出棧入棧的過程。


每個棧幀包含三部分資料:本地變數(引數+方法內的變數)、運算元棧和其它資料,本文主要涉及本地變數和運算元棧。




先看看後置++的實現:


public static void main(String[] args){
    int i= 0;
    i = i++;
}

編譯之後的位元組碼如下:

iconst_0  //把數值0 push到運算元棧
istore_1 // 把運算元棧寫回到本地變數第2個位置
iload_1 // 把本地變數第2個位置的值push到運算元棧
iinc 1,1  // 把本地變量表第2個位置加1     
istore_1 // 把操作資料棧寫回本地變數第2個位置

整個過程這樣的:



可以發現變數a在執行iinc 1,1的時候已經變成1了,但是istore_1又把變數a所在位置覆蓋成了0,所以執行完i = i++,i還是原來那個值。

另外,來看下前置++的實現:




位元組碼就不再解釋了,整個過程實現如下:



和後置++不同的地方在於,在變數進入運算元棧之前,就先執行了iinc指令,所以進入運算元的值是加1後的值,最後寫回的值也是最新值。


轉載自狼哥的部落格 https://www.jianshu.com/p/7988e646a37e