Java的参数传递到底是值传递还是引用传递

写在开头

简单粗暴点,开头直接呈上答案:在Java 中参数的传递总是采用“值传递”的方式

解释一下什么是“值传递”和“引用传递”:

  • 值传递(call by value):表示方法接收的是调用者提供的值。
  • 引用传递(call by reference):表示方法接收的是调用者提供的变量地址。

也就是说,在Java中方法得到的是所有参数值的一个拷贝,方法并不能修改传递给它的任何参数变量的内容 。

乍一看有点懵,接下来我将用下面三个例子来阐述。也可以直接去看最后的结论

1、修改基本类型参数

先看下面这段代码片段

	//定义一个方法,试图将传进来的参数值增加至2倍
	public static void doubleValue(int value) {
		value = 2 * value;
	}
	
	//调用这个方法并输出
	public static void main(String[] args) {
		int i = 1;
		doubleValue(i);
		System.out.println("i=" + i);
	}

这是一个简单的例子,输出的结果显而易见,这个方法并不能将变量 i 从 1 修改成 2 。

下面我们来看看这个例子的具体过程:

  1. value 被初始化为 i 值的一个拷贝(value → 1);
  2. value 在方法体中被乘以 2 (value → 2),但此时 i 还是 1 ;
  3. 方法结束,value不再被使用(value),控制台输出" i = 1"。

因此可以得到结论:一个方法不能修改一个基本数据类型的参数

2、修改引用类型参数

先定义一个雇员类

public class Employee {
	
	private int salary;//薪资

	public Employee(int salary) {
		this.salary = salary;
	}
	//省略getter和setter
}

然后创建一个对象,并尝试修改它的状态

	//定义一个方法,试图将传进来的雇员对象的薪资提高至2倍
	public static void doubleSalary(Employee employee) {
		employee.setSalary(2*employee.getSalary());
	}

	//调用这个方法并输出
	public static void main(String[] args) {
		Employee tom = new Employee(100);
		doubleSalary(tom);
		System.out.println(tom.getSalary());
	}

控制台输出结果为 200

由此可见,我们很容易的通过一个方法修改了传入的对象的状态

下面我们来看看具体执行过程:

  1. employee 被初始化为 tom 值的拷贝,它们同时引用同一个对象。
employee
salary = 100
tom
  1. doubleSalary 方法应用于这个对象引用,使这个对象的salary属性被修改为2倍。
doubleSalary
employee
salary = 200
tom
  1. 方法结束后,参数 employee 不再使用,但变量 tom 仍然引用那个已经被修改salary属性的对象
tom
salary = 200

因此可以得到结论:一个方法可以修改一个引用类型的参数的状态

这个例子看起来似乎是Java对对象采用了引用调用?

然!
并!
不!

下面再给出一个反例来阐述这个问题。

3、交换两个引用类型参数的引用

首先我们来定义一个交换两个雇员对象的方法

	public static void swap(Employee emp1,Employee emp2) {
		Employee tmp = emp1;
		emp1 = emp2;
		emp2 = tmp;
	}

然后创建两个对象 tom 和 bob,薪水分别为 100 和 200,调用交换方法并输出

	public static void main(String[] args) {
		Employee tom = new Employee(100);
		Employee bob = new Employee(200);
		swap(tom,bob);
		System.out.println("tom's salary = " + tom.getSalary());
		System.out.println("bob's salary = " + bob.getSalary());
	}

如果 Java 对对象采用的是引用传递,那么这个方法就应该能够实现交换薪资的效果。

然而,控制台输出的结果为
tom’s salary = 100
bob’s salary = 200

可见,这个方法并没有奏效,tom 和 bob 仍然各自引用之前的对象。

我们来看一下具体的执行过程:

  1. emp1 被初始化为 tom 的拷贝,emp2 被初始化为 bob 的拷贝。
emp1
salary = 100
tom
emp2
salary = 200
bob
  1. swap方法应用于 emp1 和 emp2,使它们相互交换对象。(这里用交叉线来画比较易懂,但是这个Mermaid图我还不太会用,写出来就是下面这样了。推荐大家自己在纸上画一画帮助理解。)
emp2
salary = 100
emp1
salary = 200
bob
tom
  1. 最终,方法结束,emp1 和 emp2 不再被使用,原来的 tom 和 bob 仍然各自引用之前所引用的对象。
tom
salary = 100
bob
salary = 200

因此可以得到结论:一个方法不能让对象参数引用一个新的对象

同时也证明了: Java 对对象采用的不是引用传递

结论

通过上面三个小栗子,我们可以得到三个小结论:

  1. 一个方法不能修改一个基本数据类型的参数
  2. 一个方法可以修改一个引用类型的参数的状态
  3. 一个方法不能让对象参数引用一个新的对象

同时,也得到了最终结论: Java 的参数传递是值传递

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值