Java 传参 理解误区纠正

警告
本文最后更新于 2021-03-24,文中内容可能已过时。

以前理解的"传引用"是错的!!!

在Java中, 有两类数据类型:

  1. 基本数据类型
  2. 引用数据类型

基本数据类型直接开对应的空间存放, 给基本数据类型赋值就是直接操作该内存空间, 直接改变了该内存里的值.

比如

1
int a = 1;

a 的值就是 1.

引用数据类型就只保存地址(引用), 地址指向的内存是真正存放数据的.

所以引用在实例化的时候需要 new 一下, 开辟一个内存空间, new 返回这个内存的地址给引用变量.

比如

1
BigInteger b = new BigInteger();

这句话实际上是先开辟一块内存, 假如首地址是 0x0001, 那么可以理解成, b 的值是 0x0001.

传递参数的时候, 如果是基本数据类型, 形参和实参不是同一块内存, 而是复制了一份, 值相同而已.

同样的, 参数如果是引用数据类型, 其实不是真正的传引用, 而也是复制了一份, 只不过这个复制的是"地址".

比如

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17

public void IncreaseOne(BigInteger c) {
	c += 1;
}

public void ChangeOne(BigInteger d) {
	d = new BigInteger(1);
}

public static void main(String[] args) {
	BigInteger b = new BigInteger(0);
	System.out.println(b);
	ChangeOne(b);
	System.out.println(b);
	IncreaseOne(b);
	System.out.println(b);
}

还是假设开辟的内存首地址是 0x0001, b 的值理解成 0x0001.

当执行 ChangeOne(b) 时, d 的值也是 0x0001.

当执行 d = new BigInteger(1) 时, 假设开辟的内存首地址是 0x0100, 那么 d 的值理解为 0x0010, 此时 b 的值还是 0x0001 没变.

也就是说, 这时对 c 进行任何操作, 改变的是 0x0100 对应内存的数据, 和 0x0001 中的数据毫不相关. 所以, 第二个输出的数应该还是 0.

当执行 IncreaseOne(b) 时, c 的值是 0x0001.

c += 1 直接对 c 所引用的内存中的数据操作, 也就是 0x0001 中的数据改变了.

所以第三个输出的数应该是 1.