從學術嚴格角度來說JAVA中只有值傳遞!!!
可是就像JAVA編程規範那樣約定俗成業界習慣了說成值傳遞和引用傳遞。
值傳遞: JAVA中基本數據類型是值傳遞
引用傳遞: JAVA中引用類型是引用傳遞面試
偉大的領導人說過,實踐是檢驗真理的惟一標準。那麼就從一道面試題開始吧。
首先建立一個實體Persion類(注意idea中安裝Lombok插件)編程
import lombok.Data;
@Data
public class Persion {
int age;
String name;
int phone;
public Persion(String name) {
this.name = name;
}
}
複製代碼
以後建立一個測試類bash
import com.demo.entity.Persion;
public class TestTransferValue {
public void changeValue1(int age){
age = 30;
}
public void changeValue2(Persion persion){
persion.setName("changeValue2");
}
public void changeValue3(String string){
string = "changeValue3";
}
public static void main(String[] args) {
TestTransferValue testTransferValue = new TestTransferValue();
int age = 20;
testTransferValue.changeValue1(30);
System.out.println("age:" + age);
Persion persion = new Persion("abc");
testTransferValue.changeValue2(persion);
System.out.println("persion name :" + persion.getName());
String str = "abc";
testTransferValue.changeValue3(str);
System.out.println("str:" + str);
}
}
複製代碼
不賣關子直接上答案,從答案入手講解值傳遞與引用傳遞的區別。jvm
首先程序的入口是main函數,在內存的棧區main方法屬於棧低。
解析一: 聲明基本數據類型age以後把age的值傳遞到changeValue1函數而且把值改變爲30,此時涉及到變量做用域問題方法changeValue1中的變量age是30,可是main方法age在棧中指向的引用仍是20的,因此第一個打印是age=20;基本數據類型都是值傳遞;ide
解析二: 接下來來到了persion變量。聲明persion變量等號的左邊叫作引用,右邊new的對象存放在內存堆中,準確的說是存放在堆中新生代的伊甸園區,順便擴展一下 新生代:養老代= 1:2,新生代中分爲伊甸園區:倖存區0:倖存區1 = 8:1:1。 此篇文章不作更多jvm擴展,有須要瞭解的關注做者後續會更新JVM相關知識。persion傳遞到changeValue2中將值改變爲value2此時棧中persion指向堆中的地址值改變爲changeValue2;繼而打印結果爲persion name :changeValue2,解釋說明了引用傳遞。函數
重點來了 第三個按照上述的persion理解引用傳遞應該打印的是changeValue3,但是爲何結果不對呢?聽我娓娓道來: 鋪墊知識,JAVA在建立String對象的時候會從字符串常量池中查找是否有和新建字符串相同的常量,若是有則返回此時兩個對象的地址也就是hashcode是同樣的,不然新建一個地址保存字符串;當字符串abc傳遞到changeValue3函數以後,查找發現池中並無changeValue3字符串,此時須要新建一個地址changeValue3函數中的string變量有了新的地址;可是此改變並無改變面函數中的str 地址因此打印的事str:abc。測試
以上就是值傳遞和引用傳遞的介紹,源碼已經提供能夠自行使用System.identityHashCode函數查看變量的內存地址。 若有錯誤歡迎留言指正,感謝您的閱讀!!!ui