Scala 不可变的val与可变的ArrayBuffer
在我发布这个问题之前,我已经阅读了上面的文章。显然,如果您在val中存储了某些内容,则无法修改它,但如果您存储了一个可变集合(如ArrayBuffer),则可以修改它Scala 不可变的val与可变的ArrayBuffer,scala,scala-collections,Scala,Scala Collections,在我发布这个问题之前,我已经阅读了上面的文章。显然,如果您在val中存储了某些内容,则无法修改它,但如果您存储了一个可变集合(如ArrayBuffer),则可以修改它 scala> val b = ArrayBuffer[Int](1,2,3) b: scala.collection.mutable.ArrayBuffer[Int] = ArrayBuffer(1, 2, 3) scala> b += 1 res50: b.type = ArrayBuffer(1, 2, 3, 1
scala> val b = ArrayBuffer[Int](1,2,3)
b: scala.collection.mutable.ArrayBuffer[Int] = ArrayBuffer(1, 2, 3)
scala> b += 1
res50: b.type = ArrayBuffer(1, 2, 3, 1)
scala> b
res51: scala.collection.mutable.ArrayBuffer[Int] = ArrayBuffer(1, 2, 3, 1)
使用val
存储可变ArrayBuffer
有什么用?我假设b改变的唯一原因是valb
将内存地址保存到ArrayBuffer(1,2,3)
如果您尝试var x=1;val y=x;x=5;y
,则输出仍然为1。在这种情况下,y将实际值而不是地址存储到x
Java没有这种混淆,因为很明显,对象不能被分配给int变量
如何知道scala中的变量何时携带值,何时是内存地址?将可变集合存储在不可变变量中有什么意义
如何知道scala中的变量何时携带值,何时是内存地址
Scala始终在JVM上运行(.NET支持已中断),因此在JVM上属于基本类型的类型将被Scala视为基本类型
使用val存储可变数组缓冲区有什么用
最接近的替代方法是使用
var
存储不可变的Seq。如果该Seq非常大,那么您不希望每次对其进行更改时都复制整个Seq,但这正是您可能需要做的!那太慢了 一个简单的答案是VAL和VAR都是参考值。Scala中没有基元类型。它们都是物体
val x = 1
是一个名为x
的引用,它指向一个不可变的整数对象1
。你不能做1。换成(2)
或别的什么,所以如果你有
val value = 5
val x = value
var y = value
您可以执行y+=10
此操作将y
更改为引用新对象(5+10)
=15
。原来的5
仍为5
另一方面,您不能执行x+=10
,因为x
是val,这意味着它必须始终指向5
。所以,这不是编译
你可能想知道为什么你可以做valb=ArrayBuffer(…)
,然后做b+=something
,即使b
是一个val。这是因为+=
实际上是一个方法,而不是一个赋值。调用b+=something
会被转换为b++=(something)。方法+=
只是将一个新元素(something
)添加到其可变的自身,并返回自身以进行进一步赋值
让我们看一个例子
scala> val xs = ArrayBuffer(1,2,3)
xs: scala.collection.mutable.ArrayBuffer[Int] = ArrayBuffer(1, 2, 3)
scala> val ys = ( xs += 999 )
ys: xs.type = ArrayBuffer(1, 2, 3, 999)
scala> xs
res0: scala.collection.mutable.ArrayBuffer[Int] = ArrayBuffer(1, 2, 3, 999)
scala> ys
res1: xs.type = ArrayBuffer(1, 2, 3, 999)
scala> xs eq ys
res2: Boolean = true
这将确认
xs
和ys
指向同一(可变)阵列缓冲区。eq
方法类似于Java的==
,它比较对象标识。可变/不可变引用(val/var)和可变/不可变数据结构(ArrayBuffer,List)是不同的。因此,如果您执行另一个xs+=888
,ys
是指向可变数据结构的不可变引用,它也包含888
,不可变对象和常量值是两个不同的东西
如果将集合定义为val,则表示该集合的引用实例将始终相同。但是这个实例可以是可变的,也可以是不可变的:如果它是不可变的,您就不能在该实例中添加或删除项,反之亦然,如果它是可变的,您就可以这样做。当集合不可更改以添加或删除项时,始终创建一个副本
将可变集合存储在不可变变量中有什么意义
val a=新阵列缓冲区(1)
a=新阵列缓冲[Int]()
:9:错误:重新分配到val
它防止变量被分配到新的内存地址。实际上,尽管scala鼓励您不要使用可变状态(以避免锁定、阻塞等),但我很难给出一个实际情况的示例,其中可变状态的var或val的选择很重要。也请阅读,希望它能澄清本主题中的一些问题。一个问题:这是什么“xs.type”??要将scala中的每个数字都作为对象来实现有点困难,但是Java也有一个用于所有原语LOL的“Box”类。@windleiner,
xs.type
实际上是一种变量xs
。你能举个“创建副本”的例子吗?它是否意味着像valx=Array[Int](1,2)这样的构造;val y=(x+=5)
将起作用,因为您“创建一个副本y
”而不是在x上工作?val s=Seq(1);vals1=s++Seq(2);println(s);println(s1)代码>。如您所见,s
和s1
是两个不同的实例。
val a = new ArrayBuffer(1)
a = new ArrayBuffer[Int]()
<console>:9: error: reassignment to val