??????許多編程語言都有2種方法將參數傳遞給方法------按值傳遞和按引用傳遞。
??????與其他語言不同,Java不允許程序員選擇按值傳遞還是按引用傳遞各個參數,基本類型(byte--short--int--long--float--double--boolean--char)的變量總是按值傳遞。就對象而言,不是將對象本身傳遞給方法,而是將對象的的引用或者說對象的首地址傳遞給方法,引用本身是按值傳遞的-----------也就是說,講引用的副本傳遞給方法(副本就是說明對象此時有兩個引用了),通過對象的引用,方法可以直接操作該對象(當操作該對象時才能改變該對象,而操作引用時源對象是沒有改變的)。
??????現在說說數組:如果將單個基本類型數組的元素傳遞給方法,并在方法中對其進行修改,則在被調用方法結束執行時,該元素中存儲的并不是修改后的值,因為這種元素是按值傳遞,如果傳遞的是數組的引用,則對數組元素的后續修改可以在原始數組中反映出來(因為數組本身就是個對象,int[] a = new int[2];,這里面的int是數組元素的類型,而數組元素的修改是操作對象)。【這兒補充一句,如果只是操作數據的引用,則原數組是不會改變的!!!】看下面的例子:
public static void main(String[] args) {
aboutParamTransporting1();
}
private static void aboutParamTransporting1() {
int a = 1;
int b = 2;
swap(a, b);
System.out.printf("a=%d, b=%d \n", a, b);
int[] x = new int[] { 10, 20 };
int[] y = new int[] { 30, 50 };
System.out.println("只是改變引用,原數組不變");
swap(x, y);
System.out.printf("x={%d, %d} \n", x[0], x[1]);
System.out.printf("y={%d, %d} \n", y[0], y[1]);
System.out.println("修改原數組對象,則原數組改變");
swapAndChange(x, y);
System.out.printf("x={%d, %d} \n", x[0], x[1]);
System.out.printf("y={%d, %d} \n", y[0], y[1]);
}
private static void swap(int[] is, int[] js) {
// 只是修改引用,原數組是不改變的。
int[] x = is;
is = js;
js = x;
}
private static void swapAndChange(int[] is, int[] js) {
// 數組交換,此時操作的只是引用哦~
int[] x = is;
is = js;
js = x;
// 修改原數組
is[0] = 1;
js[0] = 2;
}
對于單個非基本類型數組的元素在方法中修改,則在被調用方法結束執行時,該元素中存儲的是修改后的值,因為這種元素是按引用傳遞的,對象的改動將在源數組的數組元素中反映出來。
下面看個小程序:
public class TestPrimitiveType {
String str = new String("good");
char[] ch = {'a', 'b', 'c'};
int i = 10;
public void change(String str, char[] ch, int i) {
str = "test ok";
ch[0] = 'g';
i++;
}
public static void main(String[] args) {
TestPrimitiveType testPrimitiveType = new TestPrimitiveType();
testPrimitiveType.change(testPrimitiveType.str, testPrimitiveType.ch, testPrimitiveType.i);
System.out.println(testPrimitiveType.i);
System.out.println(testPrimitiveType.str);
System.out.println(testPrimitiveType.ch);
}
}
str是String類型的引用,i是基本類型變量,ch是數組名,也是數組對象的引用
在chang()方法里,str="test ok",是一個新的對象把首地址放在引用變量str上;
而ch[0]='g';因為傳的是數組的引用,而此時ch[0]='g';是對數組元素的操作,能修改源數組的內容;
i是整型值,只是把值copy了一份給方法,在方法的變化是不改變的源i的。
所以結果是:
10
good
gbc
現在咱們把代碼變化一下:
public class TestPrimitiveType {
String str = new String("good");
char[] ch = {'a', 'b', 'c'};
int i = 10;
public void change(String str, char ch, int i) {
str = "test ok";
ch = 'g';
this.i = i + 1;
}
public static void main(String[] args) {
TestPrimitiveType testPrimitiveType = new TestPrimitiveType();
testPrimitiveType.change(testPrimitiveType.str, testPrimitiveType.ch[0], testPrimitiveType.i);
System.out.println(testPrimitiveType.i);
System.out.println(testPrimitiveType.str);
System.out.println(testPrimitiveType.ch);
}
}
仔細觀察下實參以及入參有何變化?
change()方法里的入參char[] ch變成--------------char ch;
這次傳遞的是個char值的單個數組元素,按照上面的解析,此時ch='9';是不影響源數組元素的。
this.i = i+1;這里面等號左邊的i是屬性i,等號右邊的i是局部變量(入參里的i);
此時i+1后賦值給屬性的i,自然會改變屬性i的值,同時15行,tt.i又是調用屬性的i.
這次的結果是:
11
good
abc
現在是不是有點明白了?
那好再看下面一個小程序
public class TestPrimitiveType {
public void change(StringBuffer x, StringBuffer y) {
x.append(y);
y = x;
}
public static void main(String[] args) {
StringBuffer bufferA = new StringBuffer("a");
StringBuffer bufferB = new StringBuffer("b");
new TestPrimitiveType().change(bufferA, bufferB);
System.out.println(bufferA + ", " + bufferB);
}
}
這次傳遞的是兩個對象的引用的值,
在方法change()里 的x.append(y), 其中引用x調用api方法append()修改了new StringBuffer("a");的內容。
y=x;是一個修改內容的對象把首地址賦值給引用變量y了,此時操作的是引用,而先前y是new StringBuffer("b");的引用變量,所以輸出結果是:
ab,b
下面是個稍難的小程序,先自己用筆畫畫過程,寫出自己的結果,而后再上機操作下,如果自己的結果和在電腦上的結果一樣,那么再碰到這類題就不難了,如果不一樣,回頭仔細體會下我前面的講解,找找原因。
public class TestPrimitiveType {
private String nn = new String("1");
private String[] mm = {"2", "5"};
void test(String nn, String[] mm) {
nn = new String("3");
this.nn = "9";
mm[0] = "4";
System.out.println("in test(), mm[0]: " + mm[0]);
mm = new String[]{"8", "7"};
System.out.println("in test(), nn:" + nn);
System.out.println("in test(), this.nn: " + this.nn);
System.out.println("in test(), mm[0]: " + mm[0]);
}
public static void main(String[] args) {
TestPrimitiveType testPrimitiveTye = new TestPrimitiveType();
testPrimitiveTye.test(testPrimitiveTye.nn, testPrimitiveTye.mm);
System.out.println(testPrimitiveTye.nn + " " + testPrimitiveTye.mm[0]);
}
}
運行結果為:
in test(), mm[0]: 4
in test(), nn:3
in test(), this.nn: 9
in test(), mm[0]: 8
9 4
具體原因看下面的注釋:
public class TestPrimitiveType {
private String nn = new String("1");
private String[] mm = {"2", "5"};
void test(String nn, String[] mm) {
nn = new String("3"); // 傳入參數變為 3
this.nn = "9";
mm[0] = "4";
System.out.println("in test(), mm[0]: " + mm[0]); // 4, 對外面有影響
mm = new String[]{"8", "7"}; // new, 跟原來的mm沒關系了。指向了新的引用地址
System.out.println("in test(), nn:" + nn); // 傳入的參數修改后的值 3
System.out.println("in test(), this.nn: " + this.nn); // 改變了, 9
System.out.println("in test(), mm[0]: " + mm[0]); // 新的mm, 此時mm[0]為 8
}
public static void main(String[] args) {
TestPrimitiveType testPrimitiveTye = new TestPrimitiveType();
testPrimitiveTye.test(testPrimitiveTye.nn, testPrimitiveTye.mm);
System.out.println(testPrimitiveTye.nn + " " + testPrimitiveTye.mm[0]); // 9 4
}
}
參考文獻: