我认为我已经牢牢掌握了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的实例的原始引用永远丢失,而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引用的对象创建另一个“名称”,而是复制它。 / p>
为什么会这样?我找不到任何机制(例如,类似于C ++的“复制构造函数”),这些机制将由(似乎是)简单的引用赋值静默调用。
任何解释都会非常感激,因为两天的网络搜索已证明毫无结果。
答案 0 :(得分:5)
x += 1
will be expanded into x = x + 1
所以这不仅仅是作业。
如果您查看bigInt的来源,您会看到+创建新实例:
def + (that: BigInt): BigInt = new BigInt(this.bigInteger.add(that.bigInteger))
实际上它使用java的BigInteger,其添加操作使两个参数保持不变。
那么在一天结束时基本上发生的是引用重新分配不可变加法的复制构造函数的结果
答案 1 :(得分:1)
y = x
x += 1
BigInt是不可变的,所以+1创建了新的BigInt,这就是y不会改变的原因。 y
仍然指向上一个对象,而x
指向新的BigInt对象。
答案 2 :(得分:0)
我认为它与BigInt和类似类的不变性有关,你总是得到一个新的不可变对象。