什么是值传递?

方法调用时,实际参数把它的值传递给对应的形式参数,方法执行中形式参数的改变不影响实际参数的值


实参

形参


什么是引用传递?

也称为传地址。方法调用时,实际参数的引用(地址,而不是参数的值)被传递给方法中相对应的形式参数,在方法执行中,对形式参数的操作实际上就是对实际参数的操作,方法执行中形式参数值的改变将会影响实际参数的值。

值传递和引用传递(不是引用类型传递)的区别?

值传递

引用传递

根本区别

会创建副本(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;
  }

java值传递机制 java值传递和地址传递_java值传递机制


分析:在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;
  }

java值传递机制 java值传递和地址传递_值传递_02


分析: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被初始化为两个对象引用的拷贝,这个方法交换的是这两个拷贝

总结:

  • 一个方法不能修改一个基本数据类型的参数(即数值型或布尔型)
  • 一个方法可以改变一个对象参数的状态
  • 一个方法不能让对象参数引用一个新的对象