Java - 傳參到底是哪種? pass by value or pass by reference
阿新 • • 發佈:2018-11-08
在瞭解Java傳引數是pass by value或是pass by reference之前,先了解=
賦值的用法會對理解傳參很有幫助
-
賦值(=)的用法
-
=
的意義是賦值,但是這個賦值用在 基本型別 和 物件型別 上會有非常大的差別-
如果
=
用在基本型別上,因為基本型別儲存了實際的數值,所以在為其賦值時,是直接將值複製一份新的過去-
因此假設a、b都是基本型別,如果執行了
a=b
,那麼就是將b的內容直接複製一份新的給a,之後如果改變了a的值,也不會影響到b -
此處的基本型別,泛指 int、long、boolean....和其包裝型態 Integer、Long、Boolean....,只要是這些型別的變數,都適用基本型別的
=
-
-
但如果
=
用在物件型別上,因為在使用物件操作時,實際儲存的其實是物件的引用,所以在為其賦值時,實際上只是把 "引用" 從一個地方複製到另一個地方-
因此假設c、d都是物件型別,如果執行了
c=d
,那麼c和d都會指向原本只有d指向的那個物件,而原本c的那個物件因為沒人引用了,所以會被垃圾回收清理掉
-
-
-
具體例項
-
t1、t2是基本型別的
=
效果,t3、t4是物件型別的=
效果
class Tank { int level; } public class Main { public static void main(String[] args) throws InterruptedException { Tank t1 = new Tank(); Tank t2 = new Tank(); t1.level = 1; t2.level = 2; System.out.println("t1: " + t1.level + ", t2: " + t2.level); t1.level = t2.level; //此處只是基本型別的賦值,所以t1、t2仍舊指到兩個不同物件 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); } }
t1: 1, t2: 2 t1: 2, t2: 2 t1: 100, t2: 2 ---- t3: 3, t4: 4 t3: 4, t4: 4 t3: 100, t4: 100
-
-
-
pass by value 和 pass by reference
-
和
=
一樣,只要掌握好基本型別實際儲存的是"值",而物件型別儲存的是"引用",就能瞭解到底是pass by value還是pass by reference-
基本型別 pass by value,物件型別 pass by reference
class Tank { int level; } public class Main { public static void main(String[] args) throws InterruptedException { 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) throws InterruptedException { 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
-
-