java中i=i++的問題

yuan22003發表於2011-08-27
java中i=i++的問題
2009-10-15 17:19
最近老是看到問這樣問題的人,來解釋下:

int i = 0;
i = i++;
結果還是0
為什麼?

程式的執行順序是這樣的:因為++在後面,所以先使用i,“使用”的含義就是i++這個表示式的值是0,但是並沒有做賦值操作,它在整個語句的最後才做賦值,也就是說在做了++操作後再賦值的,所以最終結果還是0

讓我們看的更清晰點:
int i = 0;//這個沒什麼說的
i = i++;//等效於下面的語句:

int temp = i;//這個temp就是i++這個表示式的值
i++; //i自增
i = temp;//最終,將表示式的值賦值給i

這是java裡的實現,當然在其他的語言如c或是c++中可能並不是這麼處理的,每種語言都有各自的理由去做相應的處理。

這給我們一個警示:不要在單個的表示式中對相同的變數賦值超過一次

-----------------------------------

讓我們從位元組碼層次看一看,原始碼如下:

public class Test {

    public static void main(String... args) {

         int i = 0;

         i = i++;

        System.out.println(i);

    }

}

 

使用javac編譯後再使用javap -c Test反編譯這個類檢視它的位元組碼,如下(只摘取main方法):

 

public static void main(java.lang.String[]);

  Code:

   0:   iconst_0

   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

   

這裡,我從第0行開始分析(分析中【】表示棧,棧的底端在左邊,頂端在右邊):

0:將常數0壓入棧,棧內容:【0】

1:將棧頂的元素彈出,也就是0,儲存到區域性變數區索引為為1(也就是變數i)的地方。棧內容:【】

2:將區域性變數區索引為1(也就是變數i)的值壓入棧,棧內容:【0】

3:將區域性變數區索引為1(也就是常量i)的值加一,此時區域性變數區索引為1的值(也就是i的值)是1。棧內容:【0】

6:將棧頂元素彈出,儲存到區域性變數區索引為1(也就是i)的地方,此時i又變成了0。棧內容:【】

7:獲取常量池中索引為2所表示的類變數,也就是System.out。棧元素:【】

10:將區域性變數區索引為1的值(也就是i)壓入棧。棧元素:【0】

11:呼叫常量池索引為3的方法,也就是System.out.println

14:返回main方法

相關文章