为什么说Java中只有值传递?
1. 方法中参数的传递方式
我们都知道,在调用一个有参方法时,会把实际参数传递给形式参数,而这个传递的过程有两种方式,分别为值传递和引用传递,它们的定义为:
- 值传递:指在调用函数时将实际参数复制一份传递到函数中,这样在函数中如果对形式参数进行修改,将不会影响到实际参数。
- 引用传递:指在调用函数时将实际参数的地址直接传递到函数中,那么在函数中对形式参数所进行的修改,将影响到实际参数。
由定义可知,值传递和引用传递的区别就在于:有没有创建副本。值传递创建了副本,方法体中无法改变实际参数;引用传递没有创建副本,直接将实际参数的地址传递给了形式参数,方法体中可以改变实际参数。
2. 为什么说Java中只有值传递?
Java的数据类型分为基本类型和引用类型,很多人基于此认为:调用方法传递的参数是基本类型则为值传递,调用方法传递的参数是引用类型则为引用传递。
实际上真的如此吗?我们来看下面的几个例子。
当传递的参数为基本类型时:
public static void main(String[] args) {
int sum = 10;
System.out.println("修改前的sum值:"+sum);
change(sum);
System.out.println("修改后的sum值:"+sum);
}
public static void change(int sum) {
sum = 20;
System.out.println("形参num值:"+sum);
}
程序输出结果为:
修改前的sum值:10
形参num值:20
修改后的sum值:10
由结果可知,传递基本数据类型时,在函数中修改的仅仅是形参,对实参的值的没有影响。
当传递的参数为引用类型时:
public static void main(String[] args) {
Person person = new Person(20, "张三");
System.out.println("修改前:"+person);
change(person);
System.out.println("修改后:"+person);
}
public static void change(Person person) {
person.setAge(30);
person.setName("王五");
System.out.println("形参person的值:"+person);
}
程序输出结果为:
修改前:Person{age=20, name='张三'}
形参person的值:Person{age=30, name='王五'}
修改后:Person{age=30, name='王五'}
由输出结果可知,实参的值竟然被改变了,那按照上面的引用传递的定义,实际参数的值被改变了,这不就是引用传递了么?
实际上,当传递的参数为引用类型时,程序传递的不是对象本身,而是对象的引用,它的值为对象的地址。所以,当传递的参数为引用类型时,要判断是否为引用传递,就要看传递的引用所指向的地址是否会被改变。
我们再来看下面的例子:
public static void main(String[] args) {
Person person = new Person(20, "张三");
System.out.println("修改前:"+person);
change(person);
System.out.println("修改后:"+person);
}
public static void change(Person person) {
person =new Person();
person.setAge(30);
person.setName("王五");
System.out.println("形参person的值:"+person);
}
为了显示的更形象,Person对象没有覆盖toString方法,程序输出的结果为:
修改前:main.test.Person@1540e19d
形参person的值:main.test.Person@677327b6
修改后:main.test.Person@1540e19d
由结果我们可以知道,person传递给形参的只是一个副本,在方法体里让形参引用新的对象,并没有改变person的地址值,所以本质上还是值传递。
有个比喻很形象,你传递的参数只是一把钥匙的复制品,方法拿着钥匙的复制品进入房间,不管对房间里的任何地方进行修改,或者修改钥匙的复制品,钥匙本身不会有任何改变。
所以说,Java中只有值传递。
浙公网安备 33010602011771号