為了便于理解,會將參數(shù)傳遞分為按值傳遞和按引用傳遞。按值傳遞是傳遞的值的拷貝,按引用傳遞傳遞的是引用的地址值,所以有“在java里參數(shù)傳遞都是按值傳遞”、“引用也是按值傳遞的”這些說法。
基本數(shù)據(jù)類型作為參數(shù)傳遞
基本數(shù)據(jù)類型作為參數(shù)傳遞時都是傳遞值的拷貝。 指的是方法調用中,傳遞的是值的拷貝,無論怎么改變這個拷貝,原值是不會改變的。
也即是說實參把它的值傳遞給形參,對形參的改變不會影響實參的值。
public class Test {
public static void main(String[] args) {
Test test1 = new Test();
int i = 5;
System.out.println("調用前的i=" + i);
test1.testPassParameter(i);
//傳遞后,testPassParameter方法中對形參i的改變不會影響這里的i
System.out.println("調用后的i=" + i);
}
public void testPassParameter(int i) {
i = 10;//這里只是對形參的改變
System.out.println("tpp方法中的i=" + i);
}
}
輸出結果:
調用前的i=5
tpp方法中的i=10
調用后的i=5
對象作為參數(shù)傳遞
對象作為參數(shù)傳遞時,在方法內改變對象的值,有時原對象跟著改變,而有時又沒有改變。就會讓人對“傳值”和“傳引用”產(chǎn)生疑惑。
先看看兩種情況的例子。
public class Test {
public static void main(String[] args) {
StringBuffer s1 = new StringBuffer("hello");
StringBuffer s2 = new StringBuffer("hello");
changeStringBuffer(s1, s2);
System.out.println("s1=" + s1);
System.out.println("s2=" + s2);
}
public static void changeStringBuffer(StringBuffer ss1, StringBuffer ss2) {
ss1.append("world");
ss2 = ss1;
}
}
輸出結果:
s1=helloworld
s2=hello
分析如下:
//(1)s1,s2指向字符串的地址不同,假設為地址1,地址2
StringBuffer s1 = new StringBuffer("hello");
StringBuffer s2 = new StringBuffer("hello");

//(2)調用changeStringBuffer方法
changeStringBuffer(s1, s2);
//調用后會將s1,s2的地址(地址1,地址2)傳給ss1,ss2,即現(xiàn)在ss1也指向地址1,ss2也指向地址2

//(3)ss1所指向字符串的值變?yōu)閔elloworld,調用者s1的值相應變化。
ss1.append("world");
//ss2將指向ss1指向的地址(地址1),但此時s2依舊指向地址2,s2的值在調用前后不變。
ss2 = ss1;

所以,s1的輸出為helloworld,s2的輸出結果為hello。
(注意,這里為了區(qū)分,s1,s2和ss1,ss2用了不同的名稱,但有時候形參與實參的名字相同,其實兩者變量是完全不同的,一個是main方法中的變量,一個是changeStringBuffer()中的變量。)
可以看出,在java中對象作為參數(shù)傳遞時,傳遞的是引用的地址,是把對象在內存中的地址拷貝了一份傳給了參數(shù)。
拓展:
基本數(shù)據(jù)類型的包裝類型在傳遞參數(shù)時其實也是“按引用傳遞的”,只是因為包裝類型變量都是不可變量,容易誤解。
String是final類型,是個特殊的類,對它的一些操作符是重載的。比如:
String str = "hello";//等價于String str=new String("hello");
String str = "hello";
str = str + "world";//等價于str = new String(new StringBuffer(str).append("world"));
從以上分析,現(xiàn)在可以更易理解下面的代碼:
public class Test {
public static void fun(String str, char ch[]) {
str = "world";
ch[0] = 'd';
}
public static void main(String[] args) {
String str = new String("hello");
char[] ch = {'a', 'b', 'c'};
fun(str, ch);
System.out.println(str);
System.out.println(ch);
}
}
輸出結果
hello
dbc
方法調用時,名稱相同的實參和形參并不一樣,一個是main()中的str,指向存放"hello"的內存地址。一個是fun()中的str,str="world",相當于new String("world")。String是final類型,將在堆中重新分配一個內存空間存放"world"。ch[0]='d',對象的內容發(fā)生改變。

所以main()中str變量存放的對象內容依然是"hello"。ch從"abc"變?yōu)?dbc"。