CoreJava读书笔记--对象与类(四)--方法参数
方法参数
在程序设计语言中,将参数传递给方法(或函数)有两种传递方式:
①按值调用(call by value):表示方法接收的是调用者提供的值。
②按引用调用(call by reference):表示方法接收的是调用者提供的变量地址。
按引用调用时,方法可以修改传递引用所对应的变量值;按值调用时,方法不能修改传递值调用所对应的变量值。
而Java程序设计语言总是采用按值调用,也就是说:方法得到的是所有参数值得一个拷贝,特别是,方法不能修改传递给它的任何参数变量的内容。
我们假定一个方法可以将参数值增加至3倍:
package Test;
public class Demo1 {
public static void main(String[] args) {
double percent = 10;
tripleValue(percent);
System.out.println(percent);
}
public static void tripleValue(double x) {
x=3*x;
}
}
我们可以看到,调用这个方法后,percent值还是10,并没有发生改变。
具体执行过程:
1)x被初始化为percent值得一个拷贝(也就是10);
2)x被乘以3后等于30。但是percent仍然是10;
3)这个方法结束后,参数变量x不再使用
从上面可以看出当参数是基本数据类型的时候,方法是不能修改基本数据类型的参数的。但是我们知道,方法参数除了是基本数据类型外,还可以是对象的引用作为参数,那么这样的参数又是什么情况呢?
实现一个将员工薪金提高两倍的操作:
public static void tripleSalary(Employee e)
{
e.raiseSalary(200);
}
当调用该方法时:harry = new Employee(...);
tripleSalary(harry);
具体执行过程为:
1)x被初始化为harry值得拷贝,这里是一个对象的引用
2)raiseSalary方法应用于这个对象的引用。x和harry同时引用的那个Employee对象的薪金提高了200%
3)方法结束后,参数变量x不再使用。当然,对象变量harry继续引用那个薪金增至3倍的雇员对象。
我们可以看到,实现一个改变对象参数状态的方法并不难,因为方法得到的是对象引用的拷贝,对象的引用及其他的拷贝还是引用了这个对象。
public static void swap(Employee x,Employee y)
{
Employee temp = x;
x=y;
y=temp;
}
如果Java对对象采用的是按引用调用,那么上述方法就应该能实现交换数据的效果:
Employee a = new Employee("Alice",....);
Employee b = new Employee("Bob",....);
swap(a,b);
但是,方法并没有改变存储在变量a,b中对象的引用,swap方法的参数x和y都初始化为两个对象引用的拷贝,而该方法交换的只是这两个拷贝。并且在方法结束时,x和y都没有了,而原来的a和b还是引用方法调用前的对象。
----------------------------------------------------------------------------------------------------------------------------------
总结:所以上述过程说明,Java程序设计语言采用的不是引用调用,实际上,对象引用是按值传递的。Java中方法参数的使用情况:
①一个方法不能修改一个基本数据类型的参数
②一个方法可以改变一个对象参数的状态
③一个方法不能让对象参数引用一个新的对象
package CoreJava;
/**
* This program demonstrates parameter passing in Java
* call by value
* @author 弓长小月
*
*/
public class ParamTest {
public static void main(String[] args) {
/*
* Test1:Methods can't modify numeric parameters;
*/
System.out.println("Testing tripleValue:");
double percent = 10;
System.out.println("Before : percent="+percent);
tripleValue(percent);
System.out.println("After : percent="+percent);
/*
* Test2:Methods can change the state of object parameters
*/
System.out.println("\nTesting tripleSalary:");
Employee3 harry = new Employee3("Harry",50000);
System.out.println("Before salary : salary = "+harry.getSalary());
tripleSalary(harry);
System.out.println("After salary : salary = "+harry.getSalary());
/*
* Test3:Methods can't attach new object to object parameters
*/
System.out.println("\nTesting swap");
Employee3 a = new Employee3("Alice",70000);
Employee3 b = new Employee3("Bob",50000);
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 method : x = "+x);
}
public static void tripleSalary(Employee3 x) {
x.raiseSalary(200);
System.out.println("End of method : salary="+x.getSalary());
}
public static void swap(Employee3 x,Employee3 y) {
Employee3 temp = x;
x=y;
y=temp;
System.out.println("End of method : x= "+x.getName());
System.out.println("End of method : y= "+y.getName());
}
}
class Employee3{
private String name;
private double salary;
public Employee3(String n,double s) {
this.salary=s;
this.name=n;
}
public String getName() {
return name;
}
public double getSalary() {
return salary;
}
public void raiseSalary(double byPercent) {
double raise = salary*byPercent/100;
salary+=raise;
}
}