今天在班裡學了自增操作,先看一個簡單的案例:
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.為啥要寫這玩意 因為上面說了有學生問!