当面试官问我————Java是值传递还是引用传递?
面試官:你好,你能說出下面個程序的執行結果嗎?
public class Test {public static void main(String[] args) {String name = "Scott";int age = 5;User user = new User();user.setName(name);user.setAge(age);System.out.println("before change user = " + user);change(user, name, age);System.out.println("name = " + name);System.out.println("age = " + age);System.out.println("after change user = " + user);}public static void change(User user, String name, int age) {name = "Tom";age = 20;user.setName(name);user.setAge(age);}static class User {private String name;private int age;public String getName() {return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}@Overridepublic String toString() {return "{name : " + name + ", age : " + age + "}";}} }我:執行結果是:
面試官:恩,你的答案完全正確。age是一個基本類型變量,User、String都是引用類型變量,但是在調用change()方法之后,實參name和age都沒有改變,而user對象改變了。那么可不可以說調用change()方法時,User對象是引用傳遞,age是值傳遞?可是String的傳遞方式又是什么呢?它的表現和age相同,但本身確是引用對象,這該如何解釋呢?
我:Java和C++不同,C++中有引用傳遞的函數調用方式,而Java中只有值傳遞。
首先,值傳遞的官方解釋是:
值傳遞是指在調用函數時將實際參數復制一份傳遞到函數中,這樣在函數中如果對參數進行修改,將不會影響到實際參數。
其次,引用傳遞的官方解釋是:
引用傳遞是指在調用函數時將實際參數的地址傳遞到函數中,那么在函數中對參數所進行的修改,將影響到實際參數。?
一句話概括值傳遞和引用傳遞的區別:
值傳遞是傳遞實參副本,函數修改不會影響實參;引用傳遞是傳遞實參地址,函數修改會影響實參。
面試官:恩,那你可不可以結合上面的程序題,解釋一下這句話呢?
我:好的。針對于上面程序的應用場景,在調用change()方法的時候,user、name、age三個變量都是值傳遞。
其中,user對象是將引用拷貝了一份,引用是對象的地址,change()中對user的修改,并沒有影響到這個地址,而是修改了對象屬性。產生混淆的關鍵在于人們看到對象本身被函數修改了,就錯誤的認為這是引用傳遞。但我們區分值傳遞還是引用傳遞的關鍵在于實參是否被函數所修改,對于user對象來說地址才是實參!但如果你在change()方法中修改user引用的地址,即新創建一個新的user對象的話,就會看到main方法中的user并沒有任何改變,也就反向印證了它實際上是值傳遞。
name變量自然也是將name引用拷貝一份傳遞給change()方法,根據值傳遞的定義,函數對這個副本的修改不會影響到實際參數,又因為String的final特性,name = "Tom"; 實際上就是修改了name的地址,因此,實際參數不會受函數修改的影響。
age其本身也是將數值拷貝一份傳入change(),所以任何修改都不會影響到實參。所以我們說,在Java中只有值傳遞這一種參數傳遞方式。
面試官:恩,你的理解已經非常到位了,那額外問一句,對于上面的三種類型User、String、int,當輸出結果如何時,才可以認定是引用傳遞呢?
我:對于User對象,上面的代碼實際上并不能很好的驗證這個問題,反而給人一種對象即是實參的假象。實際上,如果調用change()方法后,重新new 一個User對象后賦值給user,即改變了變量的地址。在這種情況下,main中如果可以成功打印出新對象的話,才可以認定是引用傳遞。
String類型的name也是一樣,如果在change()中 name = "Tom"; main中如果可以打印出 Tom 的話才可以認為是引用傳遞。
包括age變量,盡管它是一個基本類型變量,但在內存中,依然有地址和數據的區分,如果在change()中的修改,main中可以看到的話,才可以說是引用傳遞。
實際上,“引用傳遞”中的“引用”二字,絕對不能簡單的理解為“引用類型”中的“引用”,而應該理解為“指針”、“地址”,Java中就算是基本類型也同樣擁有“地址”和“指針”。
總結
以上是生活随笔為你收集整理的当面试官问我————Java是值传递还是引用传递?的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: spring源码分析第三天------s
- 下一篇: Java核心篇之泛型--day5