天天看點

java i_java中i=i++問題解析

今天在班裡學了自增操作,先看一個簡單的案例:

public class Test{

public static void main(String[] args){

int a=10;

int m=7+a++;// m=7+a a=a+1System.out.println(a);//11 System.out.println(m);//17}

}

i++或者++i參與到運算中的時候,有個特定的規律:

i++ : 先運算,後加1

++i : 先加1,後運算

是以上面的題,int m=7+a++;

計算過程:(1)先計算 m=7+a (2)再計算: a=a+1

是以最後結果 a=11 m=17

上面的就是個正常題,你要是上面的都沒看懂 ,那麼下面的也不用看了。。。。

今天上課有個學生問我 :i=i++ 為啥不遵照上面的規律 ???

先看一個代碼:

public class Test{

public static void main(String[] args){

int a=10;

int varNum=66;

varNum=varNum++;

System.out.println(varNum);

}

}

按照上面的道理,varNum經過 varNum=varNum++操作後 ,應該變為 67,

但是實際結果,發現varNum的值 還是66:

????為什麼?

在講解原因之前,先學習一些預備知識:

(1)棧

棧最上面是棧頂,下面是棧底 。。

局部變量的值,在記憶體分析的時候,都被放入了棧中,棧的特點是先進後出,意味着先放進去的數,會被放在下面,後進去的數,一個一個壘在上面(就像往筒中放乒乓球)

(2)虛拟機指令---假如看不懂,可以先略過這部分往下看,然後回頭再回來看~~~

要鋪墊一些簡單的虛拟機指令:(以下截圖都是我從百度找的)

第一個:bipush

第二個:istore_1

第三個:iload_1

第四個:iinc

上面的兩個技能點,是兩個鋪墊技能點,下面開始講解 varNum=varNum++運算:

首先先介紹一個JDK自帶的反編譯工具: 一個指令 javap 可以看到到底底層是怎麼執行上面的代碼的!

首先先編譯Demo.java檔案:

此時已經在我電腦的D盤train2018檔案夾下 生成了Demo.class檔案!

然後執行javap指令:

上面圖中,紅色部分,就是底層 varNum=varNum++的執行過程:

那麼通過下面的解釋,結合上面鋪墊的虛拟機指令,來講解紅色框部分:

0: bipush 10 将參數10壓入棧;

2: istore_1 棧中彈出一個數,賦給第一個局部變量:a

3: bipush 66 将參數66壓入棧;

5: istore_2 棧中彈出一個數,賦給第二個局部變量:varNum

6: iload_2 将第二個局部變量varNum的值入棧,此時棧頂的值為66

7: iinc 2, 1 指令iinc對給定的局部變量做自增操作

2, 1 表示對第2個局部變量varNum進行累加1操作 ,意味着

varNum 變為了 67

10: istore_2 棧頂彈出一個數:也就是66 賦給第二個局部變量 varNum

意味這 varNum的值 又變回66了。。白忙活了

最終列印結果 就是: 66

over~~~~

對評論的幾個意見做個解釋:

1.為什麼名字我起成了varNum而不是i

因為虛拟機指令例如istore_1

我不想讓你誤會那個指令中的i是變量名字i

2.為什麼給了一個值66

同上個原因 ,就是為了不讓你誤會istore_1的1是變量值

3.對于評論中說這玩意工作用不到的

工作中誰這樣寫,多半是腦子有泡

我講的目的是為了面試 ,是為了給需要這個問題的人看

4.為啥要寫這玩意 因為上面說了有學生問!