在 Scala 中,val
用于声明不可变的变量,这意味着一旦 val
被赋值,它的引用(即指向的内存地址)就不能再改变。然而,这并不影响对象内部的状态(即对象的属性)是否可以改变。具体来说:
1. val
的不可变性
-
val
声明的变量是不可变的,即它的引用(指向的对象)不能被重新赋值。 -
例如:
val x = 10 // x = 20 // 这行会报错reassignment to val,因为 x 是 val,不能重新赋值
-
如果
val
指向一个对象:val person = new Person("Alice", 25) // person = new Person("Bob", 30) // 这行会报错,因为 person 是 val,不能重新赋值
2. 对象内部属性的可变性
-
虽然
val
的引用不可变,但对象内部的属性是否可变,取决于对象本身的设计。 -
如果对象的属性是
var
,那么这些属性可以被修改。 -
例如:
class Person(var name: String, var age: Int)val person = new Person("Alice", 25) println(person.name) // 输出: Alice// 修改对象内部的属性 person.name = "Bob" person.age = 30println(person.name) // 输出: Bob println(person.age) // 输出: 30
在这个例子中,
person
是一个val
,它的引用不能改变,但Person
类的属性name
和age
是var
,因此可以被修改。
3. 如果对象是不可变的
-
如果对象的属性是
val
,那么对象内部的属性也不能被修改。 -
例如:
class Person(val name: String, val age: Int)val person = new Person("Alice", 25) println(person.name) // 输出: Alice// person.name = "Bob" // 这行会报错,因为 name 是 val,不能修改
在这个例子中,
Person
类的属性name
和age
是val
,因此它们的值在对象创建后就不能再改变。
4. 总结
-
val
的不可变性是指引用的不可变性,而不是对象内部状态的不可变性。 -
如果对象内部的属性是
var
,即使对象被val
引用,这些属性仍然可以被修改。 -
如果对象内部的属性是
val
,那么对象的状态就是完全不可变的。
5. 类比
可以将 val
理解为一个固定的指针(引用),指针指向的对象可以是一个可变的对象(如果对象的属性是 var
),也可以是一个不可变的对象(如果对象的属性是 val
)。
-
val
+ 可变对象:指针固定,但对象内容可以变。 -
val
+ 不可变对象:指针固定,对象内容也不可变。
6. 代码示例
class MutablePerson(var name: String, var age: Int)
class ImmutablePerson(val name: String, val age: Int)// val + 可变对象
val mutablePerson = new MutablePerson("Alice", 25)
mutablePerson.name = "Bob" // 可以修改
println(mutablePerson.name) // 输出: Bob// val + 不可变对象
val immutablePerson = new ImmutablePerson("Alice", 25)
// immutablePerson.name = "Bob" // 这行会报错,因为 name 是 val
println(immutablePerson.name) // 输出: Alice
通过这种方式,你可以更好地理解 val
和对象内部状态的关系。
(PS:以上结果是查询deepseek的结果,只是作为自己学习的一个记录)