值传递和引用传递
- 碎碎念
- 基本概念
- 形参
- 实参
- 值传递
- 引用传递
- Java只有值传递
- 实例讲解
- 当参数为基本数据类型
- 当参数为对象,实参未更新
- 当参数为对象,实参更新
碎碎念
面试时经常会被问:值传递和引用传递的区别?甚至会出一道编程题,让你写出正确答案。例如以下代码会打印什么?
public static void main(String[] args) {
StringBuffer a = new StringBuffer("A");
StringBuffer b = new StringBuffer("B");
op(a, b);
System.out.println(a + "," + b);
}
static void op(StringBuffer a, StringBuffer b) {
a.append("B");
b = a;
}
答案是打印"AB,B"。如果做对了,恭喜你!
我们下面进入理论殿堂,讲讲原因。
基本概念
形参
用来接收调用该方法时传递的参数。
实参
传递给调用方法的参数。
public static void main(String[] args) {
int x = 1;
// 此处 x 为实参
opInt(x);
}
// 此处 a 为形参
static void opInt(int a) {
a = 5;
}
值传递
调用方法时,将实际参数复制一份到该方法中。
引用传递
调用方法时,将实际参数的地址传入该方法中。
Java只有值传递
首先,必须明确一点:Java只有值传递。
这个问题在国外也争论的很厉害,不过官方给出答案了:Java只有值传递。
从概念上也很好理解:
- 基本数据类型的数据保存在栈中,可直接获取。
- 对象的数据保持在堆中,需要通过引用地址获取实际数据。
- 基本数据类型传递时,形参会复制实参的值。
- 对象传递时,形参会复制实参的引用地址。
但注意了,两个方式都说复制,也就是对象传递时,并没有把实参的引用地址传入该方法,而是复制了一份。
因此,Java只有值传递。
实例讲解
下面通过3个实例来讲解。
当参数为基本数据类型
public static void main(String[] args) {
int x = 1;
opInt(x);
System.out.println(x);
}
static void opInt(int a) {
a = 5;
}
打印结果:“1”。
结论:当参数为基本数据类型时,修改形参的值,不会影响实参。因为形参仅拷贝了实参的值。
当参数为对象,实参未更新
public static void main(String[] args) {
StringBuffer x = new StringBuffer("A");
op(x);
System.out.println(x);
}
static void op(StringBuffer a, StringBuffer b) {
a = new StringBuffer("B");
}
打印结果:“A”。
结论:当参数为对象时,修改形参的引用,不会影响实参。因为形参仅指向了实参的引用地址。" a = new StringBuffer(“B”);"操作把变量a指向了新的对象。
当参数为对象,实参更新
public static void main(String[] args) {
StringBuffer x = new StringBuffer("A");
op(x);
System.out.println(x);
}
static void op(StringBuffer a, StringBuffer b) {
a.append("B");
}
打印结果:“AB”。
结论:当参数为对象时,修改形参的指向的值,实参也会更新。因为形参指向了实参的引用地址,修改了该地址对应的值,所有该值的引用对象都会同步更新。
看到这里,第一道编程题打印“AB,B”是否能理解了呢?