今天偶然唄問到了一個java中自增運算符的問題,涉及到了堆棧,以爲挺有趣的把它記錄下來。java
int i=0;
i=i++;
結果i是多少?
這是一個常常被說起的問題,答案一直五花八門。
具體測試一下以說明問題:
代碼1:測試
- public class Test{
- public static void main(String[] args){
- int i=0;
- i=i++;
- System.out.println(i);
- }
- }
結果i依然是0.分析其反編譯後的代碼:
spa
- public static void main(java.lang.String[]);
- Code:
- 0: iconst_0 //0放到棧頂
- 1: istore_1 //把棧頂的值保存到局部變量1,也就是i中
- 2: iload_1 //把i的值放到棧頂,也就是說此時棧頂的值是0
- 3: iinc 1, 1 //注意這個指令,把局部變量1,也就是i,增長1,這個指令不會致使棧的變化,也就是說局部變量1,即i此時爲1了。
- 6: istore_1 //把棧頂的值(0)保存到局部變量1,也就是讓i爲0了,因此最後i爲0
- 7: getstatic #2;
- 10: iload_1
- 11: invokevirtual #3;
- 14: return
值得注意到是i被修改了兩次,第一次是i++;i變爲1,最後一次是i=0;因此結果i是0
代碼2:get
- public class Test2{
- public static void main(String[] args){
- int i=0;
- int j=0;
- j=i++;
- System.out.println(i);
- System.out.println(j);
- }
- }
這個結果確定都知道,i是1,j是0.一樣看反編譯以後的代碼: io
- public static void main(java.lang.String[]);
- Code:
- 0: iconst_0
- 1: istore_1 //i=0
- 2: iconst_0
- 3: istore_2 //j=0
- 4: iload_1 //把i的值放到棧頂,也就是說此時棧頂的值是0
- 5: iinc 1, 1 //局部變量1加1,也就是讓i++了,此時i已是1了,上面說過,此指令不會致使棧變化
- 8: istore_2 //把棧頂的值(注意是0)存入局部變量2,也就是j中,因此j=0
- 9: getstatic #2;
- 12: iload_1
- 13: invokevirtual #3;
- 16: getstatic #2;
- 19: iload_2
- 20: invokevirtual #3;
- 23: return
很明顯能夠看出,java是先把i的值取出來放到棧頂,咱們能夠認爲是引入了第三個變量int k=i;而後i++,這時候i爲1了,而後讓j=k;也就是0.結論,i的++運算是在對j這個變量的賦值以前完成的。
代碼3:編譯
- public class Test3{
- public static void main(String[] args){
- int i=0;
- int j=0;
- j=++i;
- System.out.println(i);
- System.out.println(j);
- }
- }
結果你們也都知道,i=1,j=1
看操做過程: class
- public static void main(java.lang.String[]);
- Code:
- 0: iconst_0
- 1: istore_1 //i=0
- 2: iconst_0
- 3: istore_2 //j=0
- 4: iinc 1, 1 //局部變量i加1,這時候i變成1了 。
- 7: iload_1 //把i的值放到棧頂,棧頂的值是1
- 8: istore_2 //j=1
- 9: getstatic #2;
- 12: iload_1
- 13: invokevirtual #3;
- 16: getstatic #2;
- 19: iload_2
- 20: invokevirtual #3;
- 23: return
對比代碼2和代碼3,關鍵的差異就是iload_1 個iinc這兩條指令的位置變了。變量