在探討 Java 傳遞參數是 pass by value 還是 pass by reference 之前,需要先了解 Java 中 =
的具體細節
賦值 =
的用法
=
的意義是賦值,但是這個賦值用在 基本類型 和 對象類型 上會有非常大的差別
=
用在基本類型上,因為基本類型儲存了實際的數值,所以在為其賦值時,是直接將值複製一份新的過去
a=b
,那麼就是將 b 的內容直接複製一份新的給 a,之後如果改變了 a 的值,也不會影響到 b=
規則=
用在對象類型上,因為在使用對象操作時,實際儲存的其實是對象的引用,所以在為其賦值時,實際上只是把 “引用” 從一個地方複製到另一個地方
c=d
,那麼 c 和 d 都會指向原本只有 d 指向的那個對象,而原本 c 的那個對象因為沒人引用了,所以會被垃圾回收清理掉int[]
還是對象類型 Tank[]
,一律存的都是引用,所以只要賦值了,也會互相影響具體實例
t1、t2是基本類型的 =
效果(不會互相影響)
t3、t4是對象類型的 =
效果(因為存的是引用,所以會互相影響)
i5、i6是基本類型的數組的 =
效果(因為存的也是引用,所以也會互相影響)
class Tank {
int level;
}
public class Main {
public static void main(String[] args) {
Tank t1 = new Tank();
Tank t2 = new Tank();
t1.level = 1;
t2.level = 2;
System.out.println("t1: " + t1.level + ", t2: " + t2.level);
//此處只是基本類型的賦值,所以t1、t2仍舊指到兩個不同對象
t1.level = t2.level;
System.out.println("t1: " + t1.level + ", t2: " + t2.level);
t1.level = 100;
System.out.println("t1: " + t1.level + ", t2: " + t2.level);
System.out.println("----");
Tank t3 = new Tank();
Tank t4 = new Tank();
t3.level = 3;
t4.level = 4;
System.out.println("t3: " + t3.level + ", t4: " + t4.level);
//此處是對象類型的賦值,所以是t3和t4都指到了同一個對象上
//而原本t3那個對象因為沒人引用了,所以會被垃圾回收清理掉
t3 = t4;
System.out.println("t3: " + t3.level + ", t4: " + t4.level);
t3.level = 100;
System.out.println("t3: " + t3.level + ", t4: " + t4.level);
System.out.println("----");
int[] i5 = {5};
int[] i6 = {6};
System.out.println("i5[0]: " + i5[0] + ", i6[0]: " + i6[0]);
//因為數组存的是引用,所以i5和i6會指到同一個地方上
i5 = i6;
System.out.println("i5[0]: " + i5[0] + ", i6[0]: " + i6[0]);
i5[0] = 200;
System.out.println("i5[0]: " + i5[0] + ", i6[0]: " + i6[0]);
}
}
t1: 1, t2: 2
t1: 2, t2: 2
t1: 100, t2: 2
----
t3: 3, t4: 4
t3: 4, t4: 4
t3: 100, t4: 100
----
i5[0]: 5, i6[0]: 6
i5[0]: 6, i6[0]: 6
i5[0]: 200, i6[0]: 200
Pass by value or Pass by reference
和 =
一樣,只要掌握好基本類型實際儲存的是 “值”、對象類型儲存的是 “引用”、數組不論什類型存的都是 “引用”,就能了解 Java 到底什麼時候是 pass by value,什麼時候是 pass by reference
基本類型 pass by value,對象類型 pass by reference,而數組因為存的都是引用,所以也是 pass by reference
class Tank {
int level;
}
public class Main {
public static void main(String[] args) {
Tank t1 = new Tank();
Tank t2 = new Tank();
t1.level = 1;
System.out.println("t1.level: " + t1.level);
fooInt(t1.level); //基本類型pass by value
System.out.println("t1.level: " + t1.level);
t2.level = 2;
System.out.println("t2.level: " + t2.level);
fooTank(t2); //對象類型pass by reference
System.out.println("t2.level: " + t2.level);
}
public static void fooTank(Tank tank){
tank.level = 1000;
}
public static void fooInt(int level){
level = 5;
}
}
t1.level: 1
t1.level: 1
t2.level: 2
t2.level: 1000
基本類型的List、Set、Map 也是 pass by value,對象類型的 List、Set、Map 是 pass by reference
class Tank {
int level;
}
public class Main {
public static void main(String[] args) {
List<Tank> tankList = new ArrayList<>();
List<Integer> intList = new ArrayList<>();
for (int i = 1; i <= 2; i++) {
Tank tank = new Tank();
tank.level = i;
tankList.add(tank);
intList.add(i * 100);
}
System.out.println("intList: " + intList.get(0) + ", " + intList.get(1));
fooIntList(intList);
System.out.println("intList: " + intList.get(0) + ", " + intList.get(1));
System.out.println("tankList: " + tankList.get(0).level + ", " + tankList.get(1).level);
fooTankList(tankList);
System.out.println("tankList: " + tankList.get(0).level + ", " + tankList.get(1).level);
}
public static void fooTankList(List<Tank> tankList) {
for (Tank tank : tankList) {
tank.level = 500;
}
}
public static void fooIntList(List<Integer> intList) {
for (Integer i : intList) {
i = 2000;
}
}
}
intList: 100, 200
intList: 100, 200
tankList: 1, 2
tankList: 500, 500