Just declaring something as a val
instead of a var
in Scala doesn't make it immutable. In fact, var
can name an immutable value. The thing to remember is that variables in Scala, much like variables in Java, are always* references, or handles, rather than actually containing the value.
Try this in your REPL:
class Container { var content: String = "default" }
val a = new Container
val b = a
b.content = "modified"
println(a.content)
When you run val b = a
you are making b
and a
names for the same thing (not a copy, the exact same instance of Container). Because of this, when you run b.content = "modified"
the change is reflected in a
as well; it is just another name for the same thing. Note this happens even though a
is a val. All the val
means is that you can't change what instance a
is a name for.
Now think about this slight variation:
class Container { var content: String = "default" }
def update(c: Container) { c.content = "modified" }
val a = new Container
update(a)
println(a.content)
When you call update
, its parameter c
is also a reference or alias for a
. So changes are reflected outside the method call the same way they are in the earlier example.
Arrays are mutable, so they work like this as well.
*: Primitive variables (bytes, doubles, ints, etc.) are not references in Java; their boxed equivalents (java.lang.Byte...) are. It doesn't show that much since these classes/types are immutable anyway.