為什麼說Java中只有值傳遞?
阿新 • • 發佈:2020-10-28
目錄
實際引數。
1. 方法中引數的傳遞方式
我們都知道,在呼叫一個有參方法時,會把實際引數傳遞給形式引數,而這個傳遞的過程有兩種方式,分別為值傳遞和引用傳遞,它們的定義為:
- 值傳遞:指在呼叫函式時將實際引數複製一份傳遞到函式中,這樣在函式中如果對形式引數進行修改,將不會影響到實際引數。
- 引用傳遞:指在呼叫函式時將實際引數的地址直接傳遞到函式中,那麼在函式中對形式引數所進行的修改,將影響到實際引數。
由定義可知,值傳遞和引用傳遞的區別就在於:有沒有建立副本。值傳遞建立了副本,方法體中無法改變實際引數;引用傳遞沒有建立副本,直接將實際引數的地址傳遞給了形式引數,方法體中可以改變
2. 為什麼說Java中只有值傳遞?
Java的資料型別分為基本型別和引用型別,很多人基於此認為:呼叫方法傳遞的引數是基本型別則為值傳遞,呼叫方法傳遞的引數是引用型別則為引用傳遞。
實際上真的如此嗎?我們來看下面的幾個例子。
當傳遞的引數為基本型別時:
public static void main(String[] args) { int sum = 10; System.out.println("修改前的sum值:"+sum); change(sum); System.out.println("修改後的sum值:"+sum); } public static void change(int sum) { sum = 20; System.out.println("形參num值:"+sum); }
程式輸出結果為:
修改前的sum值:10
形參num值:20
修改後的sum值:10
由結果可知,傳遞基本資料型別時,在函式中修改的僅僅是形參,對實參的值的沒有影響。
當傳遞的引數為引用型別時:
public static void main(String[] args) { Person person = new Person(20, "張三"); System.out.println("修改前:"+person); change(person); System.out.println("修改後:"+person); } public static void change(Person person) { person.setAge(30); person.setName("王五"); System.out.println("形參person的值:"+person); }
程式輸出結果為:
修改前:Person{age=20, name='張三'}
形參person的值:Person{age=30, name='王五'}
修改後:Person{age=30, name='王五'}
由輸出結果可知,實參的值竟然被改變了,那按照上面的引用傳遞的定義,實際引數的值被改變了,這不就是引用傳遞了麼?
實際上,當傳遞的引數為引用型別時,程式傳遞的不是物件本身,而是物件的引用,它的值為物件的地址。所以,當傳遞的引數為引用型別時,要判斷是否為引用傳遞,就要看傳遞的引用所指向的地址是否會被改變。
我們再來看下面的例子:
public static void main(String[] args) {
Person person = new Person(20, "張三");
System.out.println("修改前:"+person);
change(person);
System.out.println("修改後:"+person);
}
public static void change(Person person) {
person =new Person();
person.setAge(30);
person.setName("王五");
System.out.println("形參person的值:"+person);
}
為了顯示的更形象,Person物件沒有覆蓋toString方法,程式輸出的結果為:
修改前:main.test.Person@1540e19d
形參person的值:main.test.Person@677327b6
修改後:main.test.Person@1540e19d
由結果我們可以知道,person傳遞給形參的只是一個副本,在方法體裡讓形參引用新的物件,並沒有改變person的地址值,所以本質上還是值傳遞。
有個比喻很形象,你傳遞的引數只是一把鑰匙的複製品,方法拿著鑰匙進入房間的複製品,不管對房間裡的任何地方進行修改,或者修改鑰匙的複製品,鑰匙本身不會有任何改變。
所以說,Java中只有值傳遞。