i++ 與++i是咱們在操做臨時變量常常用到的操做符,可是,不當心又會把本身搞的很糊塗。終其緣由,仍是沒有搞清楚其本質 。 java
i++:書上所說,當++位於變量後時,表示爲在該變量調用 後將其加1 即i = i+1; spa
++i:在調用i之間先將i加1 再進行應用 。 索引
可是,這裏有一個例子: 內存
int i = 1; get
i = i++; 編譯
System.out.println(i); 變量
問:這時的i值是多少? 原理
剛開始,有不少人會認爲是2;他們給出的理由是,i在定義時便進行了初始化--->1;而後進行i = i++ 運算,此時的i仍是1,可是隨即進行i++操做,修改了原先的i值,即i的值爲2,因此應該輸出2。 方法
其實否則,本人理解以下: im
int i = 1; i = i++;這段代碼與下面代碼相同:
int i = 1;
int temp = i;
i ++;
i = temp;
JVM會給i分闢一塊新的內存,在進行最後的賦值操做時又將這塊新內存中的值給它。也就是說,i的值仍是本身之前的值,沒有變。經過javap -c 反編譯即可看到具體信息:
從主方法內能夠看到執行過程:
iconst_1:將常數1壓棧,棧內容【1】;
istore_1:將棧頂元素彈出,也就是1(i),保存到局部變量區索引爲1的地方,棧內容【】;
iloadt_1:將局部變量區索引爲1的值壓入棧,棧內容【1】
iinc 1,1:將局部變量變量區索引爲1(i)的值加1,此時棧內容爲【2】;
istore_1:將棧頂元素彈出,存入局部變量區索引爲1的地方,此時i又變成了1,棧內容爲【】
getstatic #2:獲取常量池中索引爲2所表示的類變量,也就是System.out,棧內容【】
iload_1:將局部變量區索引爲1的值(也就是i)壓入棧,棧內容【1】
invokevirtual #3:調用常量池中索引爲3的方法---->System.out.println
return: 返回main方法
綜上,i的值是沒有變化 的,仍是先前初始化賦給的值 ----->1;
那行,咱們再改改,看下段代碼執行結果是什麼:
int i = 1;
int j = 0;
j = i++;
System.out.println(i); //這時,i的值 爲2;爲何呢?
解釋以下:
棧首先對i進行壓棧,後彈出,放在局部變量區中(索引爲1);而後對j進行壓棧,再彈出存儲在局部變量區(索引爲2);
接着,棧將局部變量區中索引爲1的值i進行壓棧,將局部變量區索引爲1的值進行加1操做--->i=2;
在對i進行加1操做後,再將棧頂元素彈出(記住,此時的棧頂元素i值 爲1),保存到局部變量區索引爲2的地方(即對j進行加1操做),j--->1;
調用System.out
將局部變量區中索引爲1的值壓入棧中,此時棧頂元素爲2;
調用常量池中System.out.println方法
return;
因此,此時i的值變爲了2 。
總結,i++與++i對於每 一我的來講,其邏輯是不難的。難點就在於對堆棧原理 理解的不夠深。