原址:http://blog.csdn.net/tutuhatec/article/details/6747774
先看4個題目:
①int i = 0;
i = i++;
②int i = 0;
i = ++i;
③int i = 0;
int j = 0;
j = i++ + i++;
④ int i = 0;
int j = 0;
j = i++ + i++ + i++;
每道題裏的i和j都是多少?
用myeclipse測試,結果分別是①i = 0,②i = 1,③i = 2,j = 1,④i = 3,j = 3。
i++和++i的問題,困擾很多人。網上、書上的解釋各種各樣。現在通過分析字節碼,來確定這兩條語句究竟是怎樣執行的。
先給出今天要用到的字節碼的含義
Bytecode |
Stack before->after |
Description |
iconst_0 |
->0 |
Loads the int value 0 onto the stack |
istore_1 |
value-> |
Store int value into variable 1 |
istore_2 |
value-> |
Store int value into variable 2 |
iinc |
No change |
Increment local variable #index by signed byte const |
iload_1 |
->value |
Loads an int value from variable 1 |
iadd |
value 1,value 2->result |
Adds 2 ints together |
說明兩點需要注意的地方:
①iinc操作是有參數的,但是在此忽略,簡寫爲iinc,此操作對應於自加操作,並且該操作不對stack有任何改變;
②iadd操作過後只在stack中保留結果result。
接下來是四段程序主要的字節碼:
①iconst_0 ②iconst_0 ③iconst_0 ④iconst_0
istore_1 istore_1 istore_1 istore_1
iload_1 iinc 1,1 iconst_0 iconst_0
iinc 1,1 iload_1 istore_2 istore_2
istore_1 istore_1 iload_1 iload_1
iinc 1,1 iinc 1,1
iload_1 iload_1
iinc 1,1 iinc 1,1
iadd iadd
istore_2 iload_1
iinc 1,1
iadd
istore_2
現在解釋①。第一步在stack中存入一個int常量0;第二步把它賦值給第一個變量,即我們的i;第三步把第一個變量i的值存入到stack中;第四步在i自身的空間進行自加,而第三步存入到stack中的值沒有變;第五步把第三步存入到stack中的值再賦值給第一個變量i。也就是說,i真的是進行自加了,但是被自己原來的值覆蓋掉了。從這裏我們可以看出,自加操作比賦值操作的優先級高。
再看②。和①比較起來,區別就在於,++i是先進行自加,然後把自加後的值存入到stack中,所以最後賦值給i的是1,不是0。
③呢?首先,③比前兩個多了一個變量,但這不是重點。往下看,把第一個變量i的值(0)存入到stack中,i自加,再第一個變量i的值(1)存入到stack中,再自加。此時stack中有兩個值了,0和1,進行加操作後的結果是1,然後賦值給第二個變量j。這裏顛覆了我們以前被告知的,加的運算優先級比自加高。這就是困擾我們的,其實,只要把值讀入到stack中,接下來就進行自加,只有得到了兩個參數,才進行加操作。
來看④。前面都和③一樣,只到進行了第一次加操作,得到的結果(1)保存在stack中,沒有賦值給j,然後再次讀入i的值(2)到stack,i自加,得到加操作的兩個參數,1和2,進行第二次加操作的結果是3,賦值給j。
到此,問題都解決了。