前置知识
值传递:值传递是指将参数的值复制一份,然后将这份副本传递给方法或赋值给新的变量。在值传递中,方法或函数无法直接修改原始变量的值,因为它们操作的是参数的副本。在值传递中,如果在方法内部修改了参数的值,那么只会影响到方法内部的副本,而原始变量的值保持不变。所以,在值传递中,方法对参数的修改不会对方法外部产生影响。
引用传递:引用传递是指将参数的引用(内存地址)传递给方法或赋值给新的变量。在引用传递中,方法或函数可以通过引用访问和修改原始变量的值。在引用传递中,方法对参数的修改会直接影响到原始变量的值。因为方法操作的是原始变量的引用,所以对引用的修改会反映到原始变量上。
Java中只有值传递
- Java方法中的参数既可以是基本类型,也可以是引用类型。
关于基本类型的参数传递,这里不在赘述,可以自行实验
- 当Java方法中参数是引用类型时,其实也是值传递。只不过传递的是对象的地址而已。这里我们可以做两个实验就能知道。
public static void main(String[] args) throws IOException{
int[] test = new int[]{1, 3, 5, 6};
change(test);
Arrays.stream(test).forEach(System.out::println); // 其中test[10]输出10
}
public static void change(int[] arr) {
arr[0] = 10;
}
- 以上的实验会误导我们任务java中参数的传递是引用类型,其实在该实验中也是值传递,只不过是参数的地址值,当我们对对应的地址进行修改的时候,对其在进行遍历的时候当然会发生变化。接下来我们通过另一个实验进一步证实参数传递的是值类型。
public class Main {
public static void main(String[] args) throws IOException{
Main.User u1 = new Main.User("quincy", 20);
Main.User u2 = new Main.User("sky", 23);
swap(u1, u2);
System.out.println("swap后u1的name: " + u1.getName()); // 输出quincy
System.out.println("swap后u2的name: " + u2.getName()); // 输出sky
}
public static void swap(Main.User u1, Main.User u2) {
User temp = u1;
u1 = u2;
u2 = temp;
System.out.println("u1的name: " + u1.getName()); // 输出sky
System.out.println("u2的name: " + u2.getName()); // 输出quincy
}
public static class User {
private String name;
private int age;
public User(String name, int age) {
this.name = name;
this.age = age;
}
public String getName(){
return name;
}
public Integer getAge() {
// 这里会自动装箱,也就是字节码中会调用Integer.valueOf()方法
return age;
}
}
}
- 由此我们可以知晓Java方法中参数的传递是值传递。即使是引用类型也是传递的地址值。只要不改变对应地址的内容,不会影响原来引用类型的改变。