什么是值传递?
方法调用时,实际参数把它的值传递给对应的形式参数,方法执行中形式参数的改变不影响实际参数的值
值
实参
形参
什么是引用传递?
也称为传地址。方法调用时,实际参数的引用(地址,而不是参数的值)被传递给方法中相对应的形式参数,在方法执行中,对形式参数的操作实际上就是对实际参数的操作,方法执行中形式参数值的改变将会影响实际参数的值。
值传递和引用传递(不是引用类型传递)的区别?
值传递 | 引用传递 | |
根本区别 | 会创建副本(Copy) | 不创建副本 |
所以 | 函数中无法改变原始对象 | 函数中可以改变原始对象 |
而在JAVA中只有值传递,基本类型传递的是值的副本,引用类型传递(不是上面说的引用传递)的是引用的副本。
值传递example:
public static void main(String[] args) {
int num1 = 3;
int num2 = 4;
change(num1, num2);
System.out.println(num1); // 打印 3
System.out.println(num2); // 打印 4
}
public static void change(int a, int b) {
int temp = a;
a = b;
b = temp;
}
分析:
在swap方法中,a、b的值进行交换,并不会影响到 num1、num2。因为,a、b中的值,只是从 num1、num2 的复制过来的。也就是说,a、b相当于num1、num2 的副本,副本的内容无论怎么修改,都不会影响到原件本身。
引用传递example:
public static void main(String[] args) {
int[] arr = {1, 2, 3, 4, 5};
System.out.println(arr[0]); //打印 1
change(arr);
System.out.println(arr[0]); // 打印 0
}
public static void change(int[] array) {
// 将数组的第一个元素变为0
array[0] = 0;
}
分析
:array 拷贝的是arr对象的引用
,也就是说 array 和 arr 指向的时同一个数组对象。 因此,外部对引用对象的改变会反映到所对应的对象上。
很多程序设计语言(特别是,C++和Pascal)提供了两种参数传递的方式:值调用和引用调用。有些程序员(甚至本书的作者)认为Java程序设计语言对对象采用的是引用调用,实际上,这种理解是不对的。由于这种误解具有一定的普遍性,所以下面给出一个反例来详细地阐述一下这个问题。
反例example
public class Test {
public static void main(String[] args) {
Student s1 = new Student("小张");
Student s2 = new Student("小李");
Test.swap(s1, s2);
System.out.println("s1:" + s1.getName()); // 小李
System.out.println("s2:" + s2.getName()); // 小张
}
public static void swap(Student x, Student y) {
// x,y交换
Student temp = x;
x = y;
y = temp;
System.out.println("x:" + x.getName()); // 小张
System.out.println("y:" + y.getName()); // 小李
}
}
分析
:方法并没有改变存储在变量 s1 和 s2 中的对象引用。swap方法的参数x和y被初始化为两个对象引用的拷贝
,这个方法交换的是这两个拷贝
总结:
- 一个方法不能修改一个基本数据类型的参数(即数值型或布尔型)
- 一个方法可以改变一个对象参数的状态
- 一个方法不能让对象参数引用一个新的对象