首先回顧一下在程式設計語言中關於如何將引數傳遞給方法的一些專業術語。按值呼叫
表示方法接收的是呼叫者提供的值。而按引呼叫
表示方法接收的是呼叫者提供的變數地址。方法可以修改按參照傳遞的變數的值,而不能修改按值傳遞的變數的值。
Java程式設計語言總是採用按值呼叫。也就是說,方法得到的是所有引數值的一個副本。具體來講,方法不能修改傳遞給它的任何引數變數的內容。
接下來,假定一個方法試圖將一個引數值增加至3倍:
public static void tripleValue(double x) {
x = 3 * x;
}
然後呼叫下面這個方法
double percent = 10;
tripleValue(percent);
不過這樣並不能起作用。呼叫這個方法之後,percent
的值還是10。具體的執行過程如下:
然而,有兩種型別的方法引數:
我們已經知道,一個方法不可能修改基本資料型別的引數,而物件參照作為引數就不同了,可以很容易得利用下面這個方法將一個員工的工資增至三倍:
public static void tripleSalary(Employee x) {
x.raiseSalary(200);
}
當呼叫
harry = new Employee(...);
tripleSalary(harry);
時,具體的執行過程為:
harry
值的一個副本,這裡就是一個物件參照。raiseSalary
方法應用與這個物件參照。x和harry同時參照的那個Employee
物件的工資提高了200%。可以看到,實現一個改變物件引數狀態的方法是完全可以的,實際上也相當常見。理由很簡單,方法得到的是物件參照的副本,原來的物件參照和這個副本都參照同一個物件。
總結
總結一下在Java中對方法引數能做什麼和不能做什麼:
public class 方法引數 {
public static void main(String[] args) {
/*
* 測試1:方法不能修改基本資料型別的引數
* */
System.out.println("測試tripleValue:");
double percent = 10;
System.out.println("之前:percent=" + percent);
tripleValue(percent);
System.out.println("之後:percent=" + percent);
/*
* 測試2:方法可以改變物件引數的狀態
* */
System.out.println("\nTesting tripleSalary");
Emplpoyee harry = new Emplpoyee("Harry", 50000);
System.out.println("之前:salary=" + harry.getSalary());
tripleSalary(harry);
System.out.println("之後:salary=" + harry.getSalary());
/*
* 測試3:方法不能讓一個物件引數參照一個新的物件
* */
System.out.println("\nTesting swap:");
Emplpoyee a = new Emplpoyee("Alice", 70000);
Emplpoyee b = new Emplpoyee("Bob", 60000);
System.out.println("之前:a=" + a.getName());
System.out.println("之前:b=" + b.getName());
swap(a, b);
System.out.println("之後:a=" + a.getName());
System.out.println("之後:b=" + b.getName());
}
public static void tripleValue(double x) {
x = 3 * x;
System.out.println("方法結束後:x=" + x);
}
public static void tripleSalary(Emplpoyee x) {
x.raiseSalary(200);
System.out.println("方法結束後:salary=" + x.getSalary());
}
public static void swap(Emplpoyee x, Emplpoyee y) {
Emplpoyee temp = x;
x = y;
y = temp;
System.out.println("方法結束後:x=" + x.getName());
System.out.println("方法結束後:y=" + y.getName());
}
};
class Emplpoyee {
private String name;
private double salary;
public Emplpoyee(String n, double s) {
name = n;
salary = s;
}
public String getName() {
return name;
}
public double getSalary() {
return salary;
}
public void raiseSalary(double byPercent) {
double raise = salary * byPercent / 100;
salary += raise;
}
}
執行結果如下:
測試tripleValue:
之前:percent=10.0
方法結束後:x=30.0
之後:percent=10.0
Testing tripleSalary
之前:salary=50000.0
方法結束後:salary=150000.0
之後:salary=150000.0
Testing swap:
之前:a=Alice
之前:b=Bob
方法結束後:x=Bob
方法結束後:y=Alice
之後:a=Alice
之後:b=Bob