JAVA 的值傳遞
預(yù)備知識
-
對象變量與對象
在 Java 中奇适,任何對象變量的值都是對存儲在另外一個地方(堆)的一個對象的引用羽嫡。
對象變量本質(zhì)仍然是變量肢专,存儲在棧中舞肆,而對象則是類的實(shí)例,存儲在堆中鸟召。如:List<Date> dateList = new ArrayList<>();
對象變量 dateList 的值是對存在于堆中的一個 ArrayList 對象的引用胆绊。如下圖:
基本類型
4 種整形:byte, short, int, long
2 種浮點(diǎn)型:float, double
1 種字符類型:char
1 種表示真值的類型:boolean值傳遞(call by value)
方法接收的是調(diào)用者提供的值氨鹏,方法不能修改對應(yīng)的變量值欧募。引用傳遞(call by reference)
方法接收的是調(diào)用者提供的變量地址,方法可以修改對應(yīng)的變量值仆抵。
JAVA 中的方法參數(shù)
Java 中僅存在值傳遞(call by value)跟继,并不存在引用傳遞(call by reference)。即 Java 方法得到的是所有參數(shù)值的一個拷貝镣丑,并不是參數(shù)值本身(地址)舔糖,方法并不能修改任何參數(shù)值的內(nèi)容。
例一
public static void main(String[] args) {
int a = 34;
System.out.println(a);
changeInt(a);
System.out.println(a);
}
public static void changeInt(int a2) {
a2 = 78;
}
上述結(jié)果是:
34
34原因:
當(dāng)調(diào)用 changeInt(a) 時莺匠,只是將 a 的值傳遞給 changeInt 方法金吗,其本身地址沒有傳遞。
changeInt 方法中的變量 a2 和 main 方法中的變量 a 存儲在棧的兩個位置趣竣,changeInt 方法中的 a2 的值改變并不影響 main 方法中的 a摇庙。-
執(zhí)行步驟:
- a2 初始化為 a 的值的拷貝(34);
- a2 被重新賦值為 78遥缕,但此時 a 的值依然是 34卫袒;
- changeInt 方法結(jié)束后,a2 的作用域結(jié)束单匣,不再被使用
例二
public static void main(String[] args) {
List<String> list = new ArrayList<>();
System.out.println(list);
changeList1(list);
System.out.println(list);
changeList2(list);
System.out.println(list);
}
public static void changeList1(List<String> list1) {
list1.add("1");
}
public static void changeList2(List<String> list2) {
list2 = new LinkedList<>();
}
輸出結(jié)果:
[]
[1]
[1]原因:
例二和例一比較類似夕凝,區(qū)別在于:此時宝穗,方法參數(shù)不是基本數(shù)據(jù)類型,而是一個對象引用码秉,也就是傳遞了變量 list 的值 —— new ArrayList 這個對象的地址逮矛,簡稱對象A。
changeList1 和 changeList2 方法得到的都是對象A的地址转砖,即變量 list1 和變量 list2 都被賦初值:對象A的地址(如圖)橱鹏。
此時請注意,變量 list1 和變量 list2 仍然不同于變量 list堪藐。它們?nèi)齻€存在在棧上的不同位置莉兰。
當(dāng)變量 list1 增加元素時,是給對象A增加元素礁竞。
而變量 list2 被指向了一個新的對象B糖荒。在方法結(jié)束時被丟棄了,并沒有改變變量 list 的值模捂。-
執(zhí)行步驟
- 變量 list 初始化為 對象 A
- 打印變量 list捶朵,也就是打印對象 A,即 []
- 變量 list1 被初始化為變量 list 的值的拷貝狂男,也就是對象 A 的地址综看;
- 變量 list1 增加元素 "1",也就是對象 A 增加元素 "1";
- 打印變量list岖食,也就是打印對象 A 的值红碑,即 [1];
- 變量 list2 被初始化為變量 list 的值的拷貝,也就是對象 A 的地址泡垃;
- 變量 list2 被賦值一個 LinkedList 對象析珊,稱之為對象 B;
- 變量 list2 的作用域結(jié)束蔑穴,對象 B 同時結(jié)束忠寻,被丟棄;
- 打印變量list存和,也就是打印對象 A 的值奕剃,即 [1];
總結(jié)
- Java 中僅有值傳遞,不存在引用傳遞捐腿。當(dāng)傳遞一個對象時纵朋,實(shí)際上傳遞的是對象參數(shù)(對象變量)的值,也就是該對象的引用的地址叙量;
- 一個方法不能修改一個基本數(shù)據(jù)類型的參數(shù)倡蝙;
- 一個方法可以改變一個對象參數(shù)的狀態(tài);
- 一個方法不能實(shí)現(xiàn)讓對象參數(shù)引用一個新的對象绞佩;