问题:
正像标题所说的,我们定义一个变量来指向一个不可变容器会引起一个让其奇怪的现象,你会发现你可用用某种方式来给它添加一个新的元素。
scala> var sisters = Vector("Melinda")
sisters: scala.collection.immutable.Vector[String] = Vector(Melinda)
scala> sisters = sisters :+ "Melissa"
sisters: scala.collection.immutable.Vector[String] = Vector(Melinda, Melissa)
scala> sisters = sisters :+ "Marissa"
sisters: scala.collection.immutable.Vector[String] = Vector(Melinda, Melissa, Marissa)
这发生了什么?我们居然改变了一个不可变容器的内容吗?
解决:
我们居然改变了一个不可变容器的内容,可是这肯定不是真的。那么真相到底是什么呢,其实是每次调用:+方法的时候,都会返回一个新的Vector,那么我们的sisters变量每次都指向了新的Vector。实际上这个结果更近似于下面的代码:
scala> var sisters = Vector("Melinda")
sisters: scala.collection.immutable.Vector[String] = Vector(Melinda)
scala> sisters = Vector("Melinda", "Melissa")
sisters: scala.collection.immutable.Vector[String] = Vector(Melinda, Melissa)
scala> sisters = Vector("Melinda", "Melissa", "Marisa")
sisters: scala.collection.immutable.Vector[String] = Vector(Melinda, Melissa, Marisa)
第二行和第三行语句实际上是改变了变量Sisters引用,指向了一个新的集合。你可以尝试改变不可变容器的内容,你会发现,这是不可能的:
scala> sisters[3] = "Marry"
<console>:1: error: identifier expected but integer literal found.
sisters[3] = "Marry"
^
总结:
刚刚接触Scala的同学,可能会对这种变量指向一个不可变容器产生疑惑,为了让大家弄清楚我们来看下变量:
一个可变变量(var),可以指向一个新的数据
一个不可变变量(val),java中final定义的变量,不可以指向一个新的数据
再来看下容器:
一个可变容器的元素是可以改变的,比如ArrayBuffer
一个不可变容器的元素是不可以改变的,比如Vecrot