Kotlin中的var和val:有什么区别?全面解析
如果您刚刚开始学习Kotlin,或者从其他语言(Java、Python、JavaScript)转过来,您可能会问的第一个问题是——为什么需要两个关键字来声明变量? 确实,如果一个关键字就能搞定,为什么还要搞复杂?答案在于这门语言的设计理念:Kotlin的诞生是为了让代码更安全、更清晰、更可预测。而var和val之间的区别并非一时兴起,而是一个管理状态的强大工具。
让我们通过示例来弄清楚何时使用var,何时使用val,以及为什么这对您的代码很重要。
什么是var和val?基本定义
我们从最简单的开始。
var(来自英文 variable)——可变变量。您可以随意为其赋予新值。val(来自英文 value)——不可变引用(只读)。初始化后,您无法更改其值。这类似于Java中的final或JavaScript中的const(有一定限制)。
下面是最简单的例子:
fun main() { var x = 10 x = 20 // 正确:var可以更改
val y = 30 // y = 40 // 编译错误:val不能重新赋值
println("x = $x, y = $y")}一切看起来都很明显,但魔鬼往往藏在细节中。
主要区别:引用的可变性 vs 对象的可变性
这里经常会产生混淆。val保证引用不会改变,但并不保证对象本身不可变。
我们通过一个列表的例子来分析:
fun main() { val numbers = mutableListOf(1, 2, 3) // numbers = mutableListOf(4, 5, 6) // 错误:val不能重新赋值
numbers.add(4) // 但这样是可以的!我们改变了对象的内容 numbers[0] = 100 // 这样也可以
println(numbers) // [100, 2, 3, 4]}请注意:我们将numbers声明为val,但可以随意添加和修改元素。为什么?因为val只保护引用本身(变量numbers),而不保护它所指向的对象。
如果您想要完全的不可变性,需要同时使用不可变集合(listOf、mapOf、setOf)和val。
fun main() { val immutableNumbers = listOf(1, 2, 3) // immutableNumbers.add(4) // 错误:listOf返回不可变列表 // immutableNumbers[0] = 100 // 错误}这是一个重要的点,在面试中经常被问到。请记住:val ≠ 不可变对象。
何时使用var,何时使用val?
Kotlin的黄金规则是:尽可能使用val,只有在确实必要时才使用var。为什么?
- 安全性。可变变量越少,在意外位置意外更改值的可能性就越小。这在多线程编程中尤其重要。
- 可读性。当您看到
val时,您立即知道值不会改变。这简化了对代码的理解。 - 函数式风格。Kotlin鼓励函数式编程,其中不可变性是关键原则之一。
下面是一个var合理的例子:
fun main() { var counter = 0 while (counter < 10) { println("Counter: $counter") counter++ // 计数器需要改变 }}而下面是一个var的不良实践示例,并且可以替换