<Core Java> 4.5 方法参数
1、专业术语:
值调用(call by value)表示方法接收的是调用者所提供的值。
引用调用(call by reference)表示方法接收的是调用者所提供的变量地址。
方法可以修改传递引用所对应的变量,但是不能修改传递值调用所对应的变量值
2、Java中总是采用值调用。即方法得到的是所有参数值的一个拷贝值,方法的作用效果均是在这个拷贝值上体现,与原本真实值无关。所以Java中的方法不能修改传递给他的任何参数变量。
例如,假定一个方法试图将参数值增至3倍:
public static void tripleValue(double x) {
x = 3 * x;
}
double percent = 10;
tripleValue(percent);
这个方法结束后percent仍为10,而对象引用参数x的值为30.但是方法结束后参数变量x不再使用,所以percent仍为10.
具体执行过程:
(1)x被初始化为percent值的一个拷贝(即x = 10)
(2)x被方法作用,值变为30.此时percent为10
(3)方法结束后,x不再使用
注意:方法参数有两种类型:基本数据类型(数字、布尔值)和对象引用。已经知道方法不能修改基本类型参数,但可以修改引用参数。
3、下面这个方法是将雇员薪金提高两倍:
public static void tripleSalary(Employee x) {
x.raiseSalary(200);
}
harry = new Employee;
tripleSalary(harry);
执行过程:
(1)x被初始化为harry的拷贝值,这里是一个引用对象;
(2)raiseSalary犯法作用在这个引用对象上。x和harry同时应用的Employee对象的薪金提高了200%
(3)方法结束后,参数变量x不再使用,但是harry继续应用被raiseSalary方法作用后的Employee对象
4、很多语言提供两种参数传递方式:值调用和引用调用。Java对对象采用的不是是引用调用。例如:
一个交换两个雇员对象的方法:
public static void swap(Employee x, Employee y) {
Employee temp = x;
x = y;
y = temp;
}
如果Java采用引用调用就应该实现交换数据的效果:
Employee a = new Employee("A");
Employee b = new Employee("B");
swap(a, b);
实际上swap方法的参数x和y被初始为两个对象的拷贝,方法实现的是两个拷贝的交换。方法结束后x和y被丢弃,最终白费力气。
说明:
Java对对象采用的不是引用调用而是值调用。
5、总结下Java中方法参数的使用情况:
一个方法不能修改基本数据类型的参数;
一个方法可以改变一个对象的参数;
一个方法不能实现让对象参数引用一个新的对象。
6、本节源代码,例4-4.
运行效果:
Testing tripleValue:
Before: percent=10.0
End of method: x=30.0
After: percent=10.0
Testing tripleSalary
Before: percent=5000.0
End of method: x=15000.0
Testing swap:
Befor: a=Alice
Befor: b=Bob
After: x=Bob
After: y=Alice
After: a=Alice
After: b=Bob
ParamTest.java:
Employee.java
- package com.vincent.javacore.paramtest;
- public class ParamTest {
- public static void main(String[] args) {
- //测试一:试图将percent提高两倍,失败了
- System.out.println("Testing tripleValue: ");
- double percent = 10;
- System.out.println("Before: percent=" + percent);
- tripleValue(percent);
- System.out.println("After: percent=" + percent);
- //测试二:成功的将一个雇员的薪金提高了两倍
- System.out.println("\nTesting tripleSalary");
- Employee harry = new Employee("harry", 5000);
- System.out.println("Before: percent=" + harry.getSalsry());
- tripleSalay(harry);
- //测试三:演示swap失败的效果
- System.out.println("\nTesting swap: ");
- Employee a = new Employee("Alice", 7000);
- Employee b = new Employee("Bob", 6000);
- System.out.println("Befor: a=" + a.getName());
- System.out.println("Befor: b=" + b.getName());
- swap(a, b);
- System.out.println("After: a=" + a.getName());
- System.out.println("After: b=" + b.getName());
- }
- private static void swap(Employee x, Employee y) {
- Employee temp = x;
- x = y;
- y = temp;
- System.out.println("After: x=" + x.getName());
- System.out.println("After: y=" + y.getName());
- }
- private static void tripleSalay(Employee x) {
- x.raiseSalary(200);
- System.out.println("End of method: x=" + x.getSalsry());
- }
- private static void tripleValue(double x) {
- x = 3 * x;
- System.out.println("End of method: x=" + x);
- }
- }
- package com.vincent.javacore.paramtest;
- public class Employee {
- private String name;
- private double salary;
- public Employee(String n, double s) {
- name = n;
- salary = s;
- }
- public String getName() {
- return name;
- }
- public double getSalsry() {
- return salary;
- }
- public void raiseSalary(double byPercent) {
- double raise = salary * byPercent / 100;
- salary += raise;
- }
- }