gpt4 book ai didi

幕后的 Java 不可变性

转载 作者:搜寻专家 更新时间:2023-11-01 03:16:07 25 4
gpt4 key购买 nike

所以,我是 Java 的新手,我想弄清楚不可变对象(immutable对象)是如何实现的,以及为什么它们看起来是可变的。我看过的很多资料似乎都“暗示”了幕后发生的事情,但我只是想澄清一下我是否走在正确的轨道上。

使用以下简单示例:

import java.math.*;

class BIMutability {

public static void main(String args[]) {

BigInteger biValue = new BigInteger("2");

for (int i=1; i<10; i++) {
System.out.println(i + ". biValue = " + biValue);
biValue = biValue.multiply(biValue);
}
}
}

运行时产生:

1. biValue = 2
2. biValue = 4
3. biValue = 16
4. biValue = 256
5. biValue = 65536
6. biValue = 4294967296
7. biValue = 18446744073709551616
8. biValue = 340282366920938463463374607431768211456
9. biValue = 115792089237316195423570985008687907853269984665640564039457584007913129639936

从表面上看,biValue 实际上是可变的。我知道情况并非如此。

因此我的理解是:biValue 本质上是一个指针变量。在运行时实例化时,为 BigInteger 类的对象分配堆,调用其构造函数(除其他事项外)根据字面值“2”初始化对象的值,并最终分配 biValue指向对象空间的指针。 (这是正确的吗?)

随后,在循环的每次连续迭代中,multiply 方法为新对象实例化分配额外的堆以包含生成的不可变值(例如,为第 4 次迭代的结果分配堆并新对象分配了值 256) 并且 biValue 被分配了一个引用新对象的指针。 (这也是正确的吗?)

(顺便说一句,根据我当时收集到的信息,之前对象的堆空间只是孤立的?或者是否立即执行了垃圾收集?如果没有,在某些情况下您可能会很快用完堆。 )

那么我是否正确地看到了这一点,或者我是否遗漏了重要的细节,或者......?

谢谢!

最佳答案

关于 multiply 如何在每次调用时创建一个新的 BigInteger 对象,并且 biValue 的值在每个迭代。

当我们说不变性时,我们的意思是对象不能被改变,而不是变量。不能改变的变量可以使用 final 修饰符声明。

是的,许多不可变的类可能“看起来”是可变的。在这种情况下,看似变异的方法将创建一个新对象。

关于循环先前迭代中 BigInteger 对象的命运,是的,它们将被垃圾收集。但是,发生这种情况的时间是不确定的。请注意,它可能填满堆,不是因为 GC 没有收集未使用的对象,而是因为数量太大。

关于幕后的 Java 不可变性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51567467/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com