1

我以为我对 Scala 对引用类型(即,从 AnyRef 派生的那些)的处理方式有一定的把握,但现在我不太确定了。

如果我创建一个像这样的简单类

class C(var x: Int = 0) {}

并定义一些实例

var a = new C
var b = new C(1)
var c = new C(2)

然后我分配

a = b

我没有得到(浅)副本,而是对实例的原始引用永远丢失,并且 a 和 b 本质上是同一个对象的“别名”。(这可以通过查看这些项目的地址来看出。)这很好,也很明智。很明显,这些是引用(而不是值),因为我可以

c = null

这不会产生错误。

现在,假设我这样做

import scala.math.BigInt
var x = BigInt("12345678987654321")
var y = BigInt("98765432123456789")
var z = x + y

这将创建三个 BigInts,分别带有 x、y 和 z,我想,它们是对它们的引用。其实我可以

z = null

并再次没有错误。然而,

y = x
x += 1

不会导致 y 改变,也就是说,在这种情况下,赋值似乎并没有简单地为 x 引用的对象创建另一个“名称”,而是复制了它

为什么会这样?我找不到任何机制(例如,类似于 C++ 的“复制构造函数”)会被(似乎是)直接引用分配静默调用。

任何解释都将不胜感激,因为两天的网络搜索已被证明是徒劳的。

4

3 回答 3

5

x += 1 将被扩展为 x = x + 1所以它不仅仅是分配。

如果您查看 bigInt 的来源,您会看到 + 创建了新实例:

def +  (that: BigInt): BigInt = new BigInt(this.bigInteger.add(that.bigInteger))

事实上,它在下面使用了 java 的 BigInteger,其添加操作使两个参数都保持不变。

所以在一天结束时基本上发生的是不可变加法的复制构造函数结果的引用重新分配

于 2013-04-11T22:06:05.430 回答
1
y = x
x += 1  

BigInt 是不可变的,因此 +1 创建了新的 BigInt,这就是 y 不变的原因。y仍然指向前一个对象,同时x指向新的 BigInt 对象。

于 2013-04-11T22:05:53.457 回答
0

我想它与 BigInt 和类似类的不变性有关,你总是得到一个新的不可变对象。

于 2013-04-11T22:20:23.980 回答