对象与类
方法参数
- 按值调用(call by value)表示方法接收到的是调用者提供的值。按引用调用(call by reference)表示方法接受的是调用者提供的变量地址。按引用调用可以修改传递引用所对应的变量值,而不能修改传递值调用所对应的变量值。
- “ 按……调用”(call by) 是一个标准的计算机科学术语,它用来描述各种程序设计语言(不只是 Java ) 中方法参数的传递方式(事实上,以前还有按名调用 ( call by name ),Algol 程序设计语言是最古老的高级程序设计语言之一,它使用的就是这种参数传递方式。不过,对于今天, 这种传递方式已经成为历史)。
- Java 程序设计语言总是采用按值调用。也就是说, 方法得到的是所有参数值的一个拷贝,特别是,方法不能修改传递给它的任何参数变量的内容。
方法参数实例:
double percent = 10;
harry.raiseSalary(percent);
假定一个方法师徒将一个参数增加3倍:
public static void tripleValue(double x)//doesn't work
{
x = 3*x;
}
调用
double percent = 10;
tripleValue(percent);
- 调用这个方法之后,percent 的值还是 10。具体实现过程为:
- x 被初始化为 percent 值的一个拷贝(也就是 10 )
- x 被乘以 3后等于 30。 但是 percent 仍然是 10 。
- 这个方法结束之后,参数变量 x 不再使用。
- 参数引用有两种类型:
- 基本数据类型(数字、布尔值)
- 对象引用
一个方法不可能修改一个基本数据类型的参数。而对象引用作为参数就不同了,可以很容易的利用下面这个方法将一个雇员的薪金提高两倍:
public static void tripleValue(Employee x)//works
{
x.raiseSalary(200);
}
调用
harry = new Employee(...);
tripleSalary(harry);
- 具体执行过程为:
- x 被初始化为 harry 值的拷贝,这里是一个对象的引用。
- raiseSalary 方法应用于这个对象引用。x 和 harry 同时引用的那个 Employee 对象的薪金提高了 200%。
- 方法结束后,参数变量 x 不再使用。当然,对象变量 harry 继续引用那个薪金增至 3倍的雇员对象
方法得到的是对象引用的拷贝,对象引用及其他的拷贝同时引用同一个对象。
- 很多程序设计语言(特别是, C++ 和 Pascal) 提供了两种参数传递的方式:值调用和引用调用。有些程序员(甚至本书的作者)认为 Java 程序设计语言对对象采用的是引用调用,实际上, 这种理解是不对的。
- 反例:交换两个雇员对象的方法
public static void swap(Employee x,Employee y)// doesn't work
{
Employee temp = x;
x = y;
y = temp;
}
- 如果 Java 对对象采用的是按引用调用,那么这个方法就应该能够实现交换数据的效果:
Employee a = new Employee("Alice",...);
Employee b = new Employee("Bob",...);
swap(a,b);// dose a now refer to Bob, b to Alice?
- 但是,方法并没有改变存储在变量 a 和 b 中的对象引用。swap 方法的参数 x 和 y 被初始化为两个对象引用的拷贝,这个方法交换的是这两个拷贝。
// x refer to Alice, y to Bob
Employee temp = x;
x = y;
y = temp;// now x refer to Bob, y to Alice
- 在方法结束时参数变量 X 和 y 被丢弃了。原来的变量 a 和 b 仍然引用这个方法调用之前所引用的对象
Java 程序设计语言对对象采用的不是引用调用,实际上, 对象引用是按值传递的。
- 下面总结一下 Java 中方法参数的使用情况:
- 一个方法不能修改一个基本数据类型的参数(即数值型或布尔型)
- 一个方法可以改变一个对象参数的状态
- 一个方法不能让对象参数引用一个新的对象
- C++ 有值调用和引用调用。 引用参数标有 & 符号。 例如, 可以轻松地实现void tripleValue(double& x) 方法或 void swap(Employee& x, Employee& y) 方法实现修改它们的引用参数的目的。