參考傳遞和值傳遞,從上學那會兒就開始強調的概念,不管你是計算機相關專業還是自學Java,一定聽過這么一句話:
方法呼叫引數如果是物件,那就是參考傳遞,如果是基本資料型別,就是值傳遞,
比如:function(Object o)就是參考傳遞,function(int i)就是值傳遞,這兩個概念似乎很好理解,我們只需要記住物件和基本資料型別的區別就行了,但是,真的是這樣嗎?
有一段代碼如下:
public static void main(String[] args) { int i = 0; System.out.println(i); change(i); System.out.println(i); } private static void change(int i) { i = 1; }
輸出結果比較好猜測,也應該都能答對:
0 0
下一個問題,如果將int改成String呢?
public static void main(String[] args) { String s = "0"; System.out.println(s); change(s); System.out.println(s); } private static void change(String s) { s = "1"; }
輸出的結果如下:
0 0
嗯?有疑問了吧?不是參考傳遞嗎?我在方法里命名修改了s的值,為什么輸出還是”0“呢?難度String作為Object有什么特殊性?
別急,繼續看下一段代碼:
public static void main(String[] args) { Person p = new Person("0"); System.out.println(p); change(p); System.out.println(p); } private static void change(Person p) { p = new Person("1"); } static class Person{ String name; public Person(String name) { this.name = name; } @Override public String toString() { return "Person{" + "name='" + name + '\'' + '}'; } }
結果會輸出什么?
Person{name='0'}
Person{name='0'}
看來String和其他Object沒什么不同,可是這樣的結果好像不太符合我們對參考傳遞的認知啊,其實我感覺這兩個概念沒有必要區分,實質是一回事,都是將堆疊中參考復制了一份傳遞到方法中,無論在方法中如何對參考操作,都是操作的副本,只是對于基本資料型別來說,值存盤在堆疊中,參考存盤的就是值,而物件來說,參考中存盤的是物件在堆中的記憶體地址,引數傳遞時生成的副本仍然指向了原來參考指向的物件,所以如果直接操作該物件是有效的,簡單畫個圖方便理解:
如果對p的操作不是將該參考指向一個新的值,而是對p指向的物件進行操作,就能看到所謂參考傳遞的效果了例如:
public static void main(String[] args) { Person p = new Person("0"); System.out.println(p); change(p); System.out.println(p); } private static void change(Person p) { p.name = "1"; } static class Person{ String name; public Person(String name) { this.name = name; } @Override public String toString() { return "Person{" + "name='" + name + '\'' + '}'; } }
此時,執行結果為:
Person{name='0'}
Person{name='1'}
總結:
Java進行方法呼叫時引數傳遞是將堆疊中的參考復制了一份到該方法的作業區,如果參考指向了一個堆中的物件,那么副本也指向這個物件,
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/553062.html
標籤:其他
下一篇:返回列表