Java中方法引數的傳遞機制
值傳遞是對基本型變數而言的,傳遞的是該變數的一個副本,改變副本不影響原變數.
引用傳遞一般是對於物件型變數而言的,傳遞的是該物件地址的一個副本, 並不是原物件本身 。
一般認為,java內的基礎型別資料傳遞都是值傳遞. java中例項物件的傳遞是引用傳遞
- 值傳遞的時候,將實參的值,copy一份給形參。
- 引用傳遞的時候,將實參的地址值,copy一份給形參。
注意:
String和包裝型別是不可變的,所以當方法引數型別為String或包裝型別的時候,也是值傳遞,即原先的值不會改變
例如:
public class Test { public static void main(String[] args) { int i = 1; String str = "hello"; Integer num = 200; int[] arr = {1,2,3,4,5}; MyData my = new MyData(); change(i,str,num,arr,my); System.out.println("i = " + i); //1 System.out.println("str = " + str);//hello System.out.println("num = " + num);//200 System.out.println("arr = " + Arrays.toString(arr));//{2,2,3,4,5} System.out.println("my.a = " + my.a);//11 } public static void change(int j, String s, Integer n, int[] a,MyData m){ j += 1; s += "world"; n += 1; a[0] += 1; m.a += 1; } } class MyData{ int a = 10; } |
為什麼會出現上面的結果呢?
第一個引數:
當我們傳入 int i的時候,由於int 為基本資料型別,所以會 ‘值傳遞’,copy一份變數,
然後在進行 j += 1操作,相當於 j = i + 1 = 1 + 1 =2,但是對i本身並沒有改變
第二個引數:
當我們傳入String型別的形參時,由於String時一個物件,所以會進行 ‘引用傳遞’
但是由於String類為一個final類,所以str是不可變的,那麼 s += 'world'會建立一個新的String物件
既然建立了一個新的物件,那麼和原先的String物件就沒有必然聯絡,所以str依然為 ‘hello’
第三個引數:
第三個引數為Integer型別,由於Integer 時一個物件,那麼會進行 ‘引用傳遞’,但是由於Integer也是一個 final類,
所以和第二個引數的情況一樣,會產生一個新的物件,和原先的物件沒有必然聯絡,所以 num依然為200
第4個引數:
由於陣列將引用存放到棧中,將資料放在堆中,所以 會進行‘引用傳遞’,
所以會將arr在棧中的引用地址傳給a,所以現在arr與a指向相同的堆地址,那麼當a進行資料修改後,
堆中的資料會進行改變,由於arr和a指向相同堆地址,所以 arr列印的時候也會改變
第5個引數:
MyData是一個物件,會進行‘引用傳遞’,和引數4的情況一樣,所以會列印11