开门见山:Java中只有值传递!
一、错误认知
基本类型是值传递,对象类型是引用传递。
二、形参与实参
1. 形式参数
方法中声明的用于接收的参数。
2. 实际参数
调用方法时传递的参数。
三、值传递与引用传递
1. 值传递(创建副本)
指将实参copy一份,赋给形参。修改形参时,不改变原本实参的值。
2. 引用传递(不创建副本)
指将地址直接传给形参。修改形参时,改变原本实参的值。
四、三段代码解释
1. 基本变量值传递
public static void main(String[] args) {
int i = 10;
pass(i );//在pass方法中输出一次
System.out.println(i);//i=10,pass方法结束后输出一次
}
public void pass(int j) {
j = 20;
System.out.println(j);//j=20
}
从代码中可以看到,i与j结果不同,是因为i传给j时,创建了一个副本给j,修改j时,跟i没关系。
2. User对象值传递
public static void main(String[] args) {
User a= new User();
a.setName("小龙女");
pass(a);
System.out.println(a);//第二次输出,user.name = '杨过'
}
public void pass(User user) {
user.setName("杨过");
System.out.println(user);//第一次输出,user.name = '杨过'
}
- 以上代码有人可能就有疑问了,不是说值传递吗,为什么形参地址的变量的“值”改变了,实参地址的变量的“值”也会改变呢?
- 注意,我这里说的是形参地址——的变量——的值改变。
- 回顾一下值传递的定义:
指将实参copy一份,赋给形参。修改形参时,不改变原本实参的值。
而我们这里改变的不是形参,而是形参所指的对象的值。 - 所以我们认为,pass(a),其实传的是地址(这个地址也是值传递)。
3. 如果还是有疑问,请看下面
public static void main(String[] args) {
User a= new User();
a.setName("小龙女");
pass(a);
System.out.println(a);//第二次输出,user.name = '小龙女'
}
public void pass(User user) {
user = new user();
user.setName("杨过");
System.out.println(user);//第一次输出,user.name = '杨过'
}
- 咦,为什么只是多了一行user = new user();就截然不同了呢?
- 因为这里,在值传递时,pass方法中new了一个新的对象,这个对象的地址与原本实参不一样。并把新的地址给了user。
- 如果此时是引用传递,那么原本对象a的地址是不是也该变为新对象的地址。但是实际没有。因此证明形式参数user也是一个创建了副本的。而创建副本的就是值传递。