問: 什麼是值傳遞?什麼是引用傳遞?爲何說 Java 中只有值傳遞?java
實參與形參:函數
值傳遞與引用傳遞:post
重點的區別在於:測試
方面 | 值傳遞 | 引用傳遞 |
---|---|---|
根本區別: | 會建立副本(copy) | 不會建立副本 |
因此: | 函數中沒法改變原始對象 | 函數中能夠改變原始對象 |
這裏須要清楚 JVM 內存的劃分及職能,即:線程
已知,JVM 會給每一個線程分配一個 Java 棧,當執行一個方法時,JVM 會往該棧中壓入一個棧幀。code
在方法中,基本數據類型的形參及變量(稱爲局部變量)的名字和值都存儲於棧中。在該方法被調用時,會爲形參在棧幀中開闢一塊內存,將實參值複製給形參,而後形參和實參之間便沒有了關聯。對象
即,此後在方法中對形參的操做不會影響到原來的實參。 例:內存
public static void main(String[] args) { int a = 21; intTest(a); System.out.println("方法執行後的a: "+a); } public static void intTest(int var){ // 將實參值複製給形參 System.out.println("傳入的形參var:"+var); // 在方法中對形參的操做不會影響到原來的實參 var = 23; System.out.println("方法內從新賦值後的形參var:"+var); }
運行結果:get
傳入的形參var:21 方法內從新賦值後的形參var:23 方法執行後的a: 21
Java 裏面的變量,要麼是基本數據類型,要麼是指向對象實例的引用類型,絕對不會是一個對象。虛擬機
對於引用數據類型的對象,變量的名和值均存儲在棧中,變量值存儲的是對象的地址,對象的實際內容存儲於堆(堆區是共享的)中。在該方法被調用時,會爲形參在棧幀中開闢一塊內存,將實參值複製給形參,即把實參指向的對象的地址複製給了形參:
1.此後在方法內部,若是沒有改變形參值(對象的地址),那麼能夠經過該形參操做原實參指向的堆中的對象。這樣雖然原對象的屬性可能發生變化,但原實參的值(指向的地址)並無發生變化。例:
// 設 Student 類對象有 name 和 age 兩個屬性 public static void main(String[] args) { Student student = new Student("張三",18); System.out.println("原對象的hashCode值:"+student.hashCode()); referenceTest(student); System.out.println("測試後的原對象:"+student); System.out.println("測試後原對象的hashCode值:"+student.hashCode()); } public static void referenceTest(Student stu){ System.out.println("改變前形參指向對象的hashCode值:"+stu.hashCode()); stu.setName("李四"); System.out.println("改變後形參指向的對象:"+stu); System.out.println("改變後形參指向對象的hashCode值:"+stu.hashCode()); }
運行結果:(這裏 hashCode 值可表明地址)
原對象的hashCode值:21685669 改變前形參指向對象的hashCode值:21685669 改變後形參指向的對象:Student{name='李四', age=18} 改變後形參指向對象的hashCode值:21685669 測試後的原對象:Student{name='李四', age=18} 測試後原對象的hashCode值:21685669
2.若是該形參指向其它對象,或者指向新 new 的對象,那麼形參值變爲新對象的內存地址。此後經過該形參操做的會是新的對象,原實參的值(指向的地址)不會發生變化。例:
// 設 Student 類對象有 name 和 age 兩個屬性 public static void main(String[] args) { Student student = new Student("張三",18); System.out.println("原對象的hashCode值:"+student.hashCode()); referenceTest(student); System.out.println("測試後的原對象:"+student); System.out.println("測試後原對象的hashCode值:"+student.hashCode()); } public static void referenceTest(Student stu){ System.out.println("改變前形參指向對象的hashCode值:"+stu.hashCode()); stu = new Student("王五",21); System.out.println("改變後形參指向的對象:"+stu); System.out.println("改變後形參指向對象的hashCode值:"+stu.hashCode()); }
運行結果:(這裏 hashCode 值可表明地址)
原對象的hashCode值:21685669 改變前形參指向對象的hashCode值:21685669 改變後形參指向的對象:Student{name='王五', age=21} 改變後形參指向對象的hashCode值:2133927002 // 有變化 測試後的原對象:Student{name='張三', age=18} 測試後原對象的hashCode值:21685669
即,此後在方法中對形參的操做並不會影響到原來的實參值(原對象的地址)。
參考博文:
若有問題,歡迎交流~ 歡迎您的點贊、收藏和評論!