我们都知道,在程序设计语言中有关将参数传递给方法(函数)的形式主要有两种,按值调用(call by value)表示方法接受的是调用者提供的值,按引用调用(call by reference)表示方法接受的是调用者提供的变量地址。一个方法可以修改传递引用所对应的变量值,而不能修改传递值所对应的变量值。这个可以借用C语言中的传递的普通参数还是指针参数来理解。当传递的是普通参数时,无论在函数中对这个参数做了怎样的加减,赋值改变,都不会影响到参数的原本,在这个函数体外,参数原本并没有改变。而进行指针参数的传递就不一样了,指针传递的是原值的存储地址,可以在这个原值的存储空间上对这个值进行加减,赋值等操作,在函数体内的对指针参数的操作就是对原本的操作,在函数调用完结之后会在原本上得到改变。
然而在Java中总是采用按值调用,也就是说,方法得到的是所有参数值得一个拷贝,方法并不能修改传给他的任何参数变量的内容。
double perent = 10;
Harry.sss(perent);
.....
public static void sss(double x)
{
x=x*3;
}
.....
具体执行过程:
1)x被初始化为一个perent值的一个拷贝(也就是10)
2)x乘以3以后等于30.但是perent仍然是10
3)这个方法结束之后,参数变量x不再使用。
一个方法不能修改一个基本类型的参数。但是对象引用作为参数就不同了,可以很容易的利用类所提供的方法来改变对象的域:
class Employee{
...
public double raiseSalary(double x)
{
raise = raise *x/100;
}
.....
public static void sss(Employee ee)
{
ee.raiseSalary(200);
}
......
}
Employee employee = new Employee(.....);
sss(employee);
具体执行过程为:
1)ee被初始化为employee值的拷贝,这里是一个对象的引用。
2)raiseSalary方法应用于这个对象。ee和employee同时引用的那个Employee对象的薪金提高了200%,
3)方法结束之后,参数变量ee不再使用,而employee变量继续引用那个薪金增致3倍的雇员对象。
通过上述传递的参数为对象时的举例,可能会有部分同学觉得Java可以传递引用,不然怎么可以修改对象的域呢,这种误解具有普遍性。首先,可以借助C语言中的指针来解释这个问题。上文说的对普通类型的传递,就相当于
void swap (int x,int y)
{
int temp=0;
temp = x;
x=y;
y=temp;
}
这样并不能在调用swap函数之后使得x,y的值进行转化;
只有传递地址时才能进行值的转化
void swap (int* x,int* y)
{
int temp=0;
temp = &x;
&x= &y;
&y=temp;
}
而当传递的是对象的引用时,就相当于:
void swap (int* x,int* y)
{
int* temp=null;
temp = x;
x = y;
y=temp;
}
可以通过x,y改变x,y指针所对应的存储空间上存储的内容,却不能改变其所对应的存储空间。这就是说,通过值传递对象,可以改变对象的域,却不能改变所对应的对象的引用。
Java程序设计语言对对象采用的是指调用,虽然传递的是对象的引用,但是只是把对象的引用的看成一个值,就相当于
void swap (int* x,int* y)
{
int* temp=null;
temp = x;
x = y;
y=temp;
}
中虽然传递的是指针,但却不能改变指针的指向。Java传递的是对象的引用,是把对象的引用看成一个值,因此不能改变对象的引用,即不能在引用别的对象,却可以改变对象域的内容。相当于不能改变指针指的存储位置,却能改变存储位置上的内容。改变存储的位置需要指针的指针,就相当于把指针看做值,把指针的指针看做值的引用,这是引用调用,因为java不是引用调用,所以就不能改变对象为引用的别的对象。
总结一下Java程序设计语言方法参数的使用情况:
1、一个方法不能修改一个基本数据类型的参数(即数值型和布尔型)
2、一个方法可以改变一个对象参数的域的状态,即属性。
3、一个方法不能让对象参数引用一个新的对象