Kotlin const vs val:区别与如何选择?
\n\n你在用 Kotlin 写代码,突然想到:“const 和 val 到底有什么区别?两者看起来都是不可变的?”问得好!这个问题甚至会让从 Java 或其他语言转过来的经验丰富的开发者感到困惑。难怪在 Stack Overflow 上,“What is the difference between "const" and "val"?” 这个话题有成千上万的浏览量。今天,我们将一劳永逸地弄清楚这个问题,从理论到实践,并用生动的代码示例来巩固理解。
准备好了吗?开始吧!
\n\n快速入门:什么是 val?
\n\n我们从最简单的开始。val(来自 value 一词)是一个不可变的引用。你可以给它赋值一次,之后再也无法更改。听起来很熟悉?是的,它类似于 Java 中的 final 或 C# 中的 readonly。
val name: String = "Alice"\nname = "Bob" // 编译错误!Val cannot be reassigned\n\n但有一个重要的细微差别:val 保证引用不会改变,但不保证对象本身的不变性。如果你将 val 与可变列表(MutableList)一起使用,你仍然可以添加和删除元素。
val numbers = mutableListOf(1, 2, 3)\nnumbers.add(4) // 可以工作!\n// numbers = mutableListOf(5, 6) // 错误!不能重新分配引用\n\nval 可以在声明时初始化,也可以在代码中稍后初始化(例如,在构造函数或 init 块中)。它的值是在程序运行时(runtime)计算的。
那 const 呢?编译时的严格守卫
\n\nconst 是 val 更严格的兄弟。它也是不可变的,但有一个超能力:值必须在编译时(compile-time)已知。换句话说,这是一个真正的常量,编译器可以像内联代码一样直接将其嵌入到代码中。
const 有严格的规则:
- \n
- 只能在文件级别(类外部)或
object/companion object内部声明。 \n - 必须是基本类型或
String类型。 \n - 不能是函数调用或计算的结果——只能是字面量或其他常量。 \n
// 正确\nconst val PI = 3.14159\nconst val APP_NAME = "MyApp"\n\n// 错误\nconst val currentTime = System.currentTimeMillis() // 错误!值在编译时未知\nconst val userName = getName() // 错误!不允许调用函数\n\n主要区别:const vs val 表格对比
\n\n为了更直观,这里有一个对比表格:
\n\n| 标准 | \nconst val | \nval | \n
|---|---|---|
| 初始化时间 | \n编译时 | \n运行时 | \n
| 声明位置 | \n顶层、object、companion object | \n任何位置(类内部、函数、构造函数) | \n
| 数据类型 | \n仅基本类型和 String | \n任何类型(包括对象、列表) | \n
| 性能 | \n最高(内联) | \n标准 | \n
| 在注解中使用 | \n是 | \n否 | \n
实际示例:注解与性能
\n\n其中一个最