今天在刷題時遇到這么一道題,程序代碼如下:
1 package algorithms.com.guan.javajicu; 2 public class Inc { 3 public static void main(String[] args) { 4 Inc inc = new Inc(); 5 int i = 0; 6 inc.fermin(i); 7 i= i ++; 8 System.out.println(i); 9 10 } 11 void fermin(int i){ 12 i++; 13 } 14 }
此程序運行的結果是:0。這個結果令我非常困惑,令我困惑的問題有兩個:
- 為什么調用fermin函數后,不影響i的值?
- i=i++;i的值為什么是0?
關於第一個問題的解答如下:
- java方法之間的參數傳遞是值傳遞而不是引用傳遞
- 每個方法都會有一個棧幀,棧幀是方法運行時的數據結構。這就是說每個方法都有自己獨享的局部變量表。(更嚴謹的說法其實是每個線程在執行每個方法時都有自己的棧幀,或者叫當前棧幀 current stack frame)
- 被調用方法fermin()的形式參數int i 實際上是調用方法main()的實際參數 i 的一個副本。
-
方法之間的參數傳遞是通過局部變量表實現的,main()方法調用fermin()方法時,傳遞了2個參數:第0個隱式參數是當前實例(Inc inc = new Inc(); 就是inc引用的副本,引用/reference 是指向對象的一個地址,32位系統這個地址占用4個字節,也就是用一個Slot來保存對象reference,這里傳遞的實際上是reference的一個副本而不是 reference本身 );第1個顯示參數是 i 的一個副本。所以 fermin()方法對 i 執行的操作只限定在其方法獨享或可見的局部變量表這個范圍內,main()方法中局部變量表中的i不受它的影響;如果main()方法和fermin()方法共享局部變量表的話,那答案的結果就會有所不同。
關於第二個問題的解答如下:
Java使用了中間緩存變量機制:
i=i++;等同於:i++是先將i賦值,然后再自增
temp=i; (等號右邊的i)
i=i+1; (等號右邊的i)
i=temp; (等號左邊的i)
而i=++i;則等同於:
i=i+1;
temp=i;
i=temp;
故調用fermin函數不會影響i的值,所以i=0,然后公式i=i++;i的值依然是0,所以程序運行的結果是0。
本人水平有限以上解釋如有錯誤,歡迎指出,以便修改。