Java方法參數傳遞

按值調用(call by value)表示方法接收的是調用者提供的值。

按引用調用(call by reference)表示方法接收的是調用者提供的變量地址。

一個方法可以修改傳遞引用所對應的變量值,而不能修改傳遞值調用所對應的變量值。

Java總是採用按值調用,方法得到的是所有參數值的一個拷貝,方法不能修改傳遞給它的任何參數變量的內容。
eg.

	public static void change(int x){
		x++;
		System.out.println("x = "+x);
	}
	public static void main(String[] args) {
		int a = 1;
		change(a);
		System.out.println("a = "+a);
	}

上面代碼執行後,輸出的結果如下

看一下具體的執行過程:

1.x被初始化爲a的一個拷貝,也就是1;

2.x執行x++後等於2,此時a依舊是1;

3.方法結束後,參數變量x不再使用。

方法參數共有兩種類型:基本數據類型和對象引用。已經看到,一個方法不能修改基本數據類型的參數,而對象引用作爲參數就不同了,看下面的例子

先建一個學生類,簡單的有姓名和年齡兩個屬性。

public class Student {
	private String name;
	private int age;
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	public Student(String name, int age) {
		super();
		this.name = name;
		this.age = age;
	}
}

利用下面方法實現年齡增長

	public static void change(Student a){
		a.setAge(a.getAge()+1);
		System.out.println(a.getName()+"'s age is "+a.getAge());
	}
	public static void main(String[] args) {
		Student stu = new Student("Stan",9);
		System.out.println(stu.getName()+"'s age is "+stu.getAge());
		change(stu);
		System.out.println(stu.getName()+"'s age is "+stu.getAge());
	}
上面代碼執行後,輸出的結果如下

已經看到,實現一個改變對象參數狀態的方法並不是一件難事,理由很簡單,方法得到的是對象引用的拷貝,對象引用及其拷貝同時引用一個對象。

看一下具體的執行過程:

1.a被初始化爲stu值的拷貝,這裏是對象的引用;

2.change方法應用於這個對象的引用,stu和a同時引用的那個Student對象的年齡+1;

3.方法結束後,參數變量a不再使用,而變量對象stu繼續引用那個年齡+1的學生對象。

回到最初的起點,很多程序設計語言提供了兩種參數傳遞的方式,就是文章開頭提到的按值調用和按引用調用,看到這裏可能大家認爲Java對對象採用的是按引用調用,實際上這種理解是錯誤的,文章開頭已經有了說明Java總是採用按值調用,方法得到的是所有參數值的一個拷貝,方法不能修改傳遞給它的任何參數變量的內容。

下面舉一個反例來闡述這個問題。

同樣是Student類,現在寫一個交換學生的方法。

	public static void change(Student a,Student b){
		Student temp = a;
		a = b;
		b = temp;
		System.out.println("a's name is "+a.getName());
		System.out.println("b's name is "+b.getName());
	}
	public static void main(String[] args) {
		Student stu1 = new Student("Stan",9);
		Student stu2 = new Student("Kyle",9);
		System.out.println(stu1.getName()+"'s age is "+stu1.getAge());
		System.out.println(stu2.getName()+"'s age is "+stu2.getAge());
		change(stu1,stu2);
		System.out.println(stu1.getName()+"'s age is "+stu1.getAge());
		System.out.println(stu2.getName()+"'s age is "+stu2.getAge());
	}
如果Java程序設計語言對對象調用採用的是按引用調用,那麼這個方法就應該能實現交換數據的效果,stu1變成Kyle而stu1變成Stan。

但是讓我們看看執行結果

方法並沒有改變存儲在變量stu1和stu2中的對象的引用。change方法的參數a和b被初始化爲兩個對象引用的拷貝,這個方法交換的是這兩個拷貝,即a和b的引用發生了改變,相互引用了對方的對象,但stu1和stu2沒有改變,沒有對stu1和stu2產生影響。

最終,在方法結束時參數變量a和b被廢棄了,原來的變量stu1和stu2依然引用這個方法調用之前所引用的對象。

這個過程說明,Java程序設計語言對對象採用的不是按引用調用,實際上,對象引用進行的是值傳遞。即把引用的值傳遞進去賦值給參數,產生一個新的引用。

下面是總結:

1.一個方法不能修改一個基本數據類型的參數;

2.一個方法可以改變一個對象參數的狀態;

3.一個方法不能讓對象參數引用一個新的對象從而傳遞出來。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章