理解--->Java中的值傳遞&引用傳遞
轉自:https://mp.weixin.qq.com/s?__biz=MzI4Njc5NjM1NQ==&mid=2247486882&idx=2&sn=0056f7c027b0db429650ea4df03985e5&chksm=ebd6328edca1bb9804927cb66bad1bb9d54e542bfea5b7ff9f9432603b919460ee601f12baf6&mpshare=1&scene=23&srcid=0113FJUlznMFE6tsTLGxjHgH#rd
值傳遞和引用傳遞
值傳遞(pass by value)是指在呼叫函式時將實際引數複製一份傳遞到函式中,這樣在函式中如果對引數進行修改,將不會影響到實際引數。
引用傳遞(pass by reference)是指在呼叫函式時將實際引數的地址直接傳遞到函式中,那麼在函式中對引數所進行的修改,將影響到實際引數,形參和實參總是指向同一個地址,形參指向哪裡實參就會指向哪裡。
java中的基本資料型別和引用資料型別
java中的基本資料型別:
-
4種整數型別:byte、short、int、long
-
2種浮點數型別:float、double
-
1種字元型別:char
-
1種布林型別:boolean
java中的引用資料型別:
-
類
-
介面
-
陣列
下面就對JAVA中傳遞引數是值傳遞還是引用傳遞展開討論
下面先來看基本資料型別
下面先來看基本資料型別
public class Test { static void testInt(int a, int b) { a=10; b=20; System。out。println("交換後 "+"a:"+a+", b:"+b); } public static void main(String[] args) { int a=1; int b=2; System。out。println("交換前 "+"a:"+a+", b:"+b); testInt(a,b); System。out。println("方法結束後"+"a:"+a+", b:"+b); } }
執行結果是這樣的:
交換前:1 2
交換後:10 20
res : 1 2
java中基本資料型別在傳遞的時候,用的是值傳遞,就是拷貝和實參一模一樣的值然後由形參進行操作,當方法結束後,形參的生命週期就會終止,實參的值並沒有受到影響。
下面來看引用資料型別
// 類的編寫 class Car { public String name; public Car() {} public Car(String name) { this。name=name; } } 下面進行測試 public class Test { public static void update1(Car car) { car。name="GTR"; System。out。println("修改後的名字是:"+car。name); } //這個方法比上面的方法多了一條a=new Car()語句 public static void update2(Car car) { car=new Car(); car。name="GTR"; System。out。println("修改後的名字是:"+car。name); } public static void main(String[] args) { Car a=new Car("AE86"); Car b=new Car("AE86"); System。out。println("呼叫update1前a的名字是:"+a。name); update1(a); System。out。println("呼叫update1後a的名字是:"+a。name); System。out。println("呼叫update2前b的名字是:"+b。name); update2(b); System。out。println("呼叫update2後b的名字是:"+b。name); } }
結果:
AE86
GTR
GTR
AE86
GTR
AE86
看完上面的update1方法,覺得引用資料型別和基本資料型別不一樣,引用資料型別傳入方法後,方法呼叫結束後物件的屬性發生了變化,認為這是引用傳遞,將物件a的地址送到了形參中,然後對形參改變實參就會改變。
但是update2馬上就推翻了這個想法,將實參送入形參後,形參馬上在堆中新建了一個物件,如果是引用傳遞,那麼此時形參和實參都是指向這個物件的,然後程式又對形參的name屬性進行了修改,那麼此時實參也會被修改,看到的結果就應該和update1一樣。但是結果卻不是這樣的,並沒有修改資料,這就說明了將物件作為實參傳入方法的形參,並不是引用傳遞。
那麼java中引用型別資料到底是怎麼回事那,下面把自己的查閱資料理解的寫下來。作為後續回顧。
Car b = new Car(“AE86”);
執行這個語句首先會在棧中建立一個b變數,然後在堆中建立一個Car類的例項,然後b指向堆中的例項。
其實在java程式中,將物件傳入形參中,也是值傳遞,基本資料型別值傳遞就是拷貝一個變數的副本;下面以update2()分析,引用資料型別就是將變數名(b)指向堆的地址複製一份,也就是說在棧中有一個變數名(car)也指向堆中b的例項。
現在執行 car =new car();就是形參car指向了堆中一個新的地址,而b還是指向原來的地址的,這樣的話,car隨便修改name屬性,是影響不到b的。最後方法結束car被釋放,堆中的新物件被GC回收。
在update1()中可以修改是因為形參和實參指向同一塊內容,當形參修改name屬性,那麼堆中的物件就會被修改,update1()執行結束後,car釋放,但堆中的例項還有變數指向,不會被回收,這時就修改了b的值。