Thinking in "++i" and "i++"

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對於每 一我的來講,其邏輯是不難的。難點就在於對堆棧原理 理解的不夠深。

相關文章
相關標籤/搜索