Простое объявление чего-либо как val
вместо var
в Scala не делает его неизменным. Фактически, var
может назвать неизменное значение. Следует помнить, что переменные в Scala, как и переменные в Java, всегда * ссылаются на или обрабатывают, а не содержат значение.
Попробуйте это в своем REPL:
class Container { var content: String = "default" }
val a = new Container
val b = a
b.content = "modified"
println(a.content)
Когда вы запускаете val b = a
, вы делаете имена b
и a
для одной и той же вещи (не копии, а точно такой же экземпляр Container). Из-за этого при запуске b.content = "modified"
изменение также отражается в a
; это просто другое название для той же вещи. Обратите внимание, что это происходит, даже если a
является значением. Все, что означает val
, это то, что вы не можете изменить имя экземпляра a
.
Теперь подумайте об этом небольшом отклонении:
class Container { var content: String = "default" }
def update(c: Container) { c.content = "modified" }
val a = new Container
update(a)
println(a.content)
Когда вы вызываете update
, его параметр c
равен , а также ссылкой или псевдонимом для a
. Поэтому изменения отображаются вне вызова метода так же, как в предыдущем примере.
Массивы являются изменяемыми, поэтому они так же работают.
*: Примитивные переменные (байты, двойные, целые и т. Д.) Не являются ссылками в Java; их коробочные эквиваленты (java.lang.Byte ...). Это не так уж много, так как эти классы / типы в любом случае неизменны.