文章目录
4.5 方法参数
程序设计语言中如何将参数传递给方法?
- 按值调用,方法接收的是调用者提供的值
- 按引用调用,方法接收的是调用者提供的变量地址
方法可以修改按引用传递的变量的值。
java语言总是按值调用。方法得到的是所有参数的一个副本。方法不能修改传递给它的任何参数变量的内容。
public static void tripleValue(double x){
x=x*3;
}
double percent=10;
tripleValue(percent);
这并不能起作用。调用方法之后,percent还是10.
具体的执行:
- x初始化为percent的一个副本,值为10.
- x乘以3=30,但是percent不变
- 方法结束,参数x不再使用
方法参数有两种:
- 基本数据类型
- 对象引用
一个方法不可能修改基本数据类型的参数。但是,对象引用作为参数就不一样了
public static void tripleSalary(Employee x){
x.raiseSalary(200);
}
harry=new Employee(...);
tripleSalary(harry);
//有点意思,这个不起眼的小栗子也是细节满满啊。
//tripleSalary()是一个静态方法,它是类的,它的参数是本类的一个对象。真不戳啊!真不戳啊!
具体执行:
- x初始化为harry值的一个副本。就是一个对象变量中存储的对象引用。
- raiseSalary方法应用于这个对象引用。x和harry同时引用一个Employee对象。这个对象在x的操作下,它的工资提高了200%。
- 方法结束后,x凉凉。结果呢,就是harry继续引用那个工资已经变成原来三倍的Employee对象。
这种方式非常常见,方法得到的是对象引用的副本,原来的对象引用和这个副本都指向同一个对象。
很多人,大量的人认为java对对象采用的是按引用调用,这是不对的,这是一个非常普遍的错误。反例如下:
交换两个Employee对象的方法:
public static void swap(Employee x,Employee y){
Employee temp=x;
x=y;
y=temp;
}
如果java对对象采用的是按引用调用,那么这个方法就能够实现交换。
var a=new Employee("Alice",...);
var b=new Employee("Bob",...);
swap(a,b);
但是,这个方法并没有改变存储在变量a和b中的对象引用。swap方法的参数x,y被初始化为两个对象引用的副本,方法交换的也是副本。
所以,白费力气。方法结束时,x和y被丢弃了。原来的a,b仍然引用之前本身引用的对象。
说明:java程序设计语言对对象采用的不是按引用调用!实际上,对象引用是按值传递的。
韩:java永远都是值传递。就是传递对象变量,传递的也是一个副本。只不过副本和原对象变量引用同一个对象。什么操作能做什么不能做可要根据这个去判断。
总结一下java中对方法参数能做什么不能做什么:
- 方法不能修改基本数据类型的参数
- 方法可以改变对象参数的状态
- 不能让一个对象参数引用一个新的对象
下面的程序将展示这几个要点:
- 首先试图将一个数值参数的值增加三倍,但没有成功
- 随后成功的将一个员工的工资增加三倍。方法结束后harry引用的对象的状态发生了变化。这个方法是通过对象引用的副本修改了所引用对象的状态。
- 最后,演示swap的失败效果。x,y互换了。而a,b没有受到影响。
public class ParamTest {
public static void main(String[] args) {
//测试一
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:");
var harry=new Employee("harry", 50000);
System.out.println("Before: salary="+harry.getSalary());
tripleSalary(harry);
System.out.println("After: salary="+harry.getSalary());
//测试三
System.out.println("\nTesting swap:");
var a=new Employee("Alice", 70000);
var b=new Employee("Bob", 60000);
System.out.println("Before: a="+a.getName());
System.out.println("Before: b="+b.getName());
swap(a, b);
System.out.println("After: a="+a.getName());
System.out.println("After: b="+b.getName());
}
public static void tripleValue(double x){
x=3*x;
System.out.println("End of the method:x="+x);
}
public static void tripleSalary(Employee x){
x.raiseSalary(200);
System.out.println("End of the method: salary="+x.getSalary());
}
public static void swap(Employee x,Employee y){
Employee temp=x;
x=y;
y=temp;
System.out.println("End of the method: x="+x.getName());
System.out.println("End of the method: y="+y.getName());
}
}
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 getSalary(){
return salary;
}
public void raiseSalary(double byPercent){
double raise=salary*byPercent/100;
salary=salary+raise;
}
}