Java的值传递问题

首先我们应该明确Java中是只存在值传递的。那么,值传递是什么呢?

值传递:指在调用函数时将实际参数复制一份传递到函数中,这样在函数中如果对参数进行修改,将不会影响到实际参数。

现在我们通过分析两种数据类型来看看Java中的值传递过程。

(1)基本数据类型

public class FirstTest {
	public void changeA(int a) {
		a = 2;
	}
	public static void main(String args[]) {
		FirstTest ft = new FirstTest();
		int a = 5;
		ft.changeA(a);
		System.out.println(a); // a = 5
	}
}

我们可以看到这个简单的例子中先把在main函数里定义了一个a = 5,然后我们想通过changeA函数来改变a的值,救过输出一看发现并没有更改成功,那么这是怎么一回事呢?

通过值传递的定义我们可以知道当a作为实际参数在函数中传值时,会复制一份a2(便于区分这么叫,其实就是changeA函数中的形参a),那么这个时候a和a2都为5,但其实他们两是两个独立的变量,那我修改a2的值为2对a就不造成影响,所以最后a仍然等于5。.


 

(2)引用数据类型

情况一:

class Second{
	public int a;
}
public class FirstTest {
	public void changeA(Second sd) {
		sd.a = 2;
	}
	public static void main(String args[]) {
		FirstTest ft = new FirstTest();
		Second sd = new Second();
		sd.a = 5;
		ft.changeA(sd);
		System.out.println(sd.a); // a = 2
	}
}

这里可以看到我们创建了一个新类Second,里面定义了一个变量a,现在我们还是想通过changeA函数来改变这个a,只不过这次我们想通过传引用数据的方式来实现。

这里我们最好了解一下Java的内存机制(可以戳这个视频,个人认为讲的非常到位),不过不了解也不要紧,大家应该都知道当new一个对象的时候会在堆中开辟一块空间,此时sd这个对象里其实存储的是这块内存空间的地址(也就是说sd指向这块内存空间),那么根据值传递的定义,当我们将sd传入changeA函数时,会复制一份sd2(实际上是changeA的形参sd),但是由于sd其实是等于一个地址,那么sd2也应该等于同样的地址,也就是说sd2页指向了那块内存空间,这时候你通过sd2去改变a也就相当于通过sd去改变a,所以a改变了。

情况二:

class Second{
	public int a;
}
public class FirstTest {
	public void changeA(Second sd) {
		sd = new Second(); //(1)
		sd.a = 2; // (2)
	}
	public static void main(String args[]) {
		FirstTest ft = new FirstTest();
		Second sd = new Second();
		sd.a = 5;
		ft.changeA(sd);
		System.out.println(sd.a); // a = 5
	}
}

这里我将changeA函数做了小小的变化,最终的结果就又改变了。前面的过程还是和之前一样的,但是在changeA函数中,由于 (1)中new又在堆中开辟了一块内存空间,再将这块空间的地址赋给了sd2,那么此时sd2就不指向原来的那块内存空间了(可以说这是sd2完全是一个新的对象),那么改变sd2的a就不会引起sd的a改变。

原文地址:https://www.cnblogs.com/z1014601153/p/12802475.html