對象傳遞(數組、類、接口)是引用傳遞,原始類型數據(整型、浮點型、字符型、布爾型)傳遞是值傳遞。
那么什么是值傳遞和應用傳遞呢?
值傳遞是指對象被值傳遞,意味着傳遞了對象的一個副本,即使副本被改變,也不會影響源對象。(因為值傳遞的時候,實際上是將實參的值復制一份給形參。)
引用傳遞是指對象被引用傳遞,意味着傳遞的並不是實際的對象,而是對象的引用。因此,外部對引用對象的改變會反映到所有的對象上。(因為引用傳遞的時候,實際上是將實參的地址值復制一份給形參。)
值傳遞和應用傳遞實例
1. 值傳遞
public static void main(String[] args) { int num1 = 10; int num2 = 20; swap(num1, num2); System.out.println("num1 = " + num1); System.out.println("num2 = " + num2); } public static void swap(int a, int b) { int temp = a; a = b; b = temp; System.out.println("a = " + a); System.out.println("b = " + b); }
結果:
a = 20
b = 10
num1 = 10
num2 = 20
解析:在swap方法中,a、b的值進行交換,並不會影響到num1、num2。因為,a、b中的值,只是從num1、num2的復制過來的。 也就是說,a、b相當於num1、num2的副本,副本的內容無論怎么修改,都不會影響到原件本身。
2. 引用傳遞
public static void main(String[] args) { int[] arr = {1,2,3,4,5}; change(arr); System.out.println(arr[0]); } public static void change(int[] array) { //將數組的第一個元素變為0 array[0] = 0; }
結果:
0
解析:無論是主函數,還是change方法,操作的都是同一個地址值對應的數組。 。因此,外部對引用對象的改變會反映到所有的對象上。
一些特殊的例子
1. StringBuffer類型傳遞
// 測試引用傳遞:StringBuffer @org.junit.Test public void method1() { StringBuffer str = new StringBuffer("AAAAAAAAAAAAAAAAAAAAAAAAA"); System.out.println(str); change1(str); System.out.println(str); } public static void change1(StringBuffer str) { str = new StringBuffer("BBBBBBBBBBBBBBBBBBBBBBBB"); }
結果:
AAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAA
解析:
很多要這個時候要問了:StringBuffer創建的明明也是對象,那為什么輸出結果依然是原來的值呢?
因為在change1
方法內部我們是新建了一個StringBuffer對象,所以str
指向了另外一個地址,相應的操作也同樣是指向另外的地址的。
public static void change1(StringBuffer str) {
str.append("CCCCCCCCCCCCCCCCC");
str.insert(3, "(DDDDDDDDDDDD)");
}
2. String類型傳遞
public void method2() { String str = new String("DDDDDDDDDDDDDDDDDDDDDDDDDDDD"); System.out.println(str); change2(str); System.out.println(str); } public static void change2(String str) { // str="EEEEEEEEEEEEEEEEEEEEEEEEEEEE"; str = new String("EEEEEEEEEEEEEEEEEEEEEEEEEEEE");
}
結果:
DDDDDDDDDDDDDDDDDDDDDDDDDDDD
DDDDDDDDDDDDDDDDDDDDDDDDDDDD
可以看到不論是執行str="abc;"
還是str = new String("abc");
str的輸出的值都不變。 按照我們上面講“StringBuffer類型傳遞”的時候說的,str="abc;"
應該會讓str的輸出的值都不變。為什么呢?因為String在創建之后是不可變的。
3. 一道類似的題目
下面的程序輸出是什么?
public class Demo { public static void main(String[] args) { Person p = new Person("張三"); change(p); System.out.println(p.name); } public static void change(Person p) { Person person = new Person("李四"); p = person; } } class Person { String name; public Person(String name) { this.name = name; } }
很明顯仍然會輸出張三
。因為change
方法中重新創建了一個Person
對象。
那么,如果把change
方法改為下圖所示,輸出結果又是什么呢?
public static void change(Person p) { p.name="李四"; }
輸出結果為 李四