参数传递问题
首先要明确,在程序设计语言中,将参数传递给方法(函数)的方式有两种:
- 按值传递:表示方法接收的是调用者提供的值;
- 按引用传递:表示方法接收的是调用者提供的地址。(引用可以理解为地址)
一个方法可以修改传递引用所对应的变量值,而不能修改传递值所对应的变量值!因为值传递实际上是对值进行拷贝后再传递,不会影响原来的值。
两个重要理解误区:
误区一、值传递和引用传递,区分的条件是传递的内容,如果是个值,就是值传递。如果是个引用,就是引用传递。
误区二、传递的参数如果是基本数据类型,那就是值传递,如果是对象,那就是引用传递。
带着这两个误区往下看,在java中参数是如何进行传递的呢?
这里先说结论避免混淆:
java语言中都是采用值传递的方式!
java中的参数类型分为两种:基本数据类型和对象引用。下面我们分别看看他们是如何传递的。
1.基本数据类型
eg1.
public static void tripleValue(double x){
x=3*x;
}
@Test
double percent=10;
tripleValue(10);
//调用这个方法后,percent的值仍然为10!
具体执行流程如下:
(1) x被初始化为percent值的一个拷贝(也就是10)
(2) x被乘以3后等于30,但是percent仍然为10
(3) 这个方法结束后,参数变量x不再使用
2.对象引用
eg2.
class Employee{
double salary;
}
public static void tripleValue(Employee x){
x.salary=3*x.salary;
}
@Test
harry=new Employee(..);
tripleValue(harry);
//执行过后,harry中的salary值变为了原来的三倍!
具体执行流程如下:
(1) harry的值是一个对象的引用,x被初始化为harry值的拷贝,也是该对象的引用
(2) tripleValue方法应用于这个对象引用。x和harry同时引用的那个Employee对象的salary值变为原来三倍。
(3) 方法结束后,参数变量x不再使用,但harry依然引用该对象。
3.一个更直观的例子
//一个交换两个雇员对象的方法
public static void swap(Employee x,Employee y){
Employee temp=x;
x=y;
y=temp;
}
@Test
Employee a=new Employee("Alice"...);
Employee b=new Employee("Bob"...);
swap(a,b);
//如果是按引用传递的话,那么交换后a中的数据应该是"Bob",b中的数据应该是"Alice",但实际上并不是这样的!
实际上,swap方法的参数x和y被初始化为两个对象引用的拷贝,在这个方法中交换的是这两个拷贝。在方法结束时,参数变量x和y被丢弃了,原来的变量a和b仍然引用这个方法调用之前所引用的对象。
所以在java中,无论是对象引用还是基本数据类型,都是按照值传递的!
4.总结
值传递和引用传递根本区别:
- 值传递:会创建副本(Copy),操作是在副本上进行的,不会改变原始数据(实参)。
- 引用传递:不创建副本,操作时在原始数据上完成的。
假设现在有一把钥匙和一个对应的房间(对象),我们需要把钥匙给别人。
a.我们将钥匙新配了一把再交给别人,那就是值传递;
b.我们直接将钥匙交给别人,那就是引用传递。
无论是值传递还是引用传递,我们都可以对房间(对象)进行操作(eg2.),但是值传递不会改变原来数据(钥匙)。