Kotlin 变量与常量 #
一、变量声明 #
1.1 val - 只读变量 #
val(value)声明只读变量,类似于 Java 的 final:
kotlin
val name: String = "Kotlin"
val age = 25 // 类型推断
// 错误:不能重新赋值
// name = "Java"
1.2 var - 可变变量 #
var(variable)声明可变变量:
kotlin
var count: Int = 0
count = 10 // 正确:可以重新赋值
var message = "Hello"
message = "World" // 正确
1.3 val vs var #
| 特性 | val | var |
|---|---|---|
| 重新赋值 | 不可以 | 可以 |
| 引用可变 | 可以(对象内容可变) | 可以 |
| 推荐程度 | 优先使用 | 需要时使用 |
kotlin
// val 引用不可变,但对象内容可变
val list = mutableListOf(1, 2, 3)
list.add(4) // 正确:修改列表内容
// list = mutableListOf() // 错误:不能重新赋值
二、类型推断 #
2.1 自动类型推断 #
Kotlin 可以根据初始值推断变量类型:
kotlin
val name = "Kotlin" // 推断为 String
val age = 25 // 推断为 Int
val price = 99.99 // 推断为 Double
val isActive = true // 推断为 Boolean
// 显式指定类型
val count: Long = 100
val score: Float = 95.5f
2.2 类型必须明确 #
没有初始值时必须指定类型:
kotlin
// 错误:无法推断类型
// val name
// 正确:显式指定类型
val name: String
name = "Kotlin"
三、声明位置 #
3.1 顶层变量 #
在类/函数外部声明:
kotlin
val APP_NAME = "MyApp"
var globalCounter = 0
fun main() {
println(APP_NAME)
globalCounter++
}
3.2 成员变量 #
在类中声明:
kotlin
class Person {
val name: String = "Unknown" // 只读属性
var age: Int = 0 // 可变属性
}
3.3 局部变量 #
在函数中声明:
kotlin
fun calculate() {
val a = 10
var b = 20
b = a + b
return b
}
四、延迟初始化 #
4.1 lateinit #
用于 var 类型的延迟初始化:
kotlin
class MainActivity {
// 延迟初始化,不需要立即赋值
lateinit var name: String
fun init() {
name = "Kotlin" // 在使用前初始化
}
fun printName() {
// 检查是否已初始化
if (::name.isInitialized) {
println(name)
}
}
}
使用限制:
- 只能用于
var - 不能用于基本类型(Int、Long、Float 等)
- 不能用于可空类型
- 必须在使用前初始化
kotlin
// 错误用法
// lateinit val name: String // 错误:必须是 var
// lateinit var age: Int // 错误:不能是基本类型
// lateinit var name: String? // 错误:不能是可空类型
4.2 lazy #
用于 val 类型的延迟初始化:
kotlin
val heavyObject: HeavyClass by lazy {
println("初始化...")
HeavyClass() // 第一次访问时才初始化
}
// 使用
println("开始")
println(heavyObject) // 此时才初始化
println(heavyObject) // 使用缓存值
lazy 特点:
- 线程安全(默认)
- 只初始化一次
- 第一次访问时初始化
kotlin
// 指定线程模式
val data by lazy(LazyThreadSafetyMode.NONE) {
loadData()
}
4.3 lateinit vs lazy #
| 特性 | lateinit | lazy |
|---|---|---|
| 变量类型 | var | val |
| 类型限制 | 非基本类型、非可空 | 无限制 |
| 初始化时机 | 手动控制 | 首次访问时 |
| 线程安全 | 否 | 是(默认) |
五、常量 #
5.1 编译时常量 #
使用 const val 声明:
kotlin
const val MAX_COUNT = 100
const val APP_NAME = "MyApp"
const val PI = 3.14159
// 错误:const 只能用于顶层或 object 中
// class MyClass {
// const val VALUE = 10 // 错误
// }
const 限制:
- 只能用于顶层或
object中 - 只能是基本类型或 String
- 必须在编译时确定值
5.2 普通常量 #
kotlin
// 普通常量(运行时常量)
val currentTime = System.currentTimeMillis()
// 编译时常量
const val VERSION = "1.0.0"
5.3 命名约定 #
常量使用全大写字母和下划线:
kotlin
const val MAX_SIZE = 100
const val DEFAULT_TIMEOUT = 30000L
const val API_BASE_URL = "https://api.example.com"
六、属性访问器 #
6.1 自定义 getter #
kotlin
val isEmpty: Boolean
get() = this.size == 0
class Circle(val radius: Double) {
val area: Double
get() = Math.PI * radius * radius
}
val circle = Circle(5.0)
println(circle.area) // 每次访问都计算
6.2 自定义 setter #
kotlin
class Person {
var name: String = ""
set(value) {
field = value.trim()
}
var age: Int = 0
set(value) {
field = if (value >= 0) value else 0
}
}
val person = Person()
person.name = " Kotlin "
println(person.name) // "Kotlin"(已去除空格)
6.3 幕后字段 #
使用 field 关键字访问实际存储:
kotlin
class Counter {
var count = 0
get() = field
set(value) {
if (value >= 0) {
field = value
}
}
}
七、类型别名 #
使用 typealias 创建类型别名:
kotlin
typealias UserMap = Map<String, User>
typealias Predicate<T> = (T) -> Boolean
typealias ClickHandler = (View) -> Unit
// 使用
val users: UserMap = mapOf()
val isAdult: Predicate<Person> = { it.age >= 18 }
八、变量作用域 #
8.1 作用域规则 #
kotlin
val globalVar = 100
fun outer() {
val outerVar = 200
fun inner() {
val innerVar = 300
println(globalVar) // 可访问
println(outerVar) // 可访问
println(innerVar) // 可访问
}
}
8.2 变量遮蔽 #
kotlin
val count = 10
fun test() {
val count = 20 // 遮蔽外部变量
println(count) // 输出 20
if (true) {
val count = 30 // 遮蔽函数级变量
println(count) // 输出 30
}
println(count) // 输出 20
}
九、最佳实践 #
9.1 优先使用 val #
kotlin
// 推荐
val name = "Kotlin"
val items = listOf(1, 2, 3)
// 只在需要时使用 var
var counter = 0
counter++
9.2 使用有意义的名称 #
kotlin
// 不推荐
val n = "Kotlin"
val a = 25
// 推荐
val name = "Kotlin"
val age = 25
9.3 延迟初始化选择 #
kotlin
// val 延迟初始化 → 使用 lazy
val database: Database by lazy { Database.connect() }
// var 延迟初始化 → 使用 lateinit
lateinit var service: ApiService
9.4 避免全局可变变量 #
kotlin
// 不推荐
var globalCounter = 0
// 推荐:使用封装
object Counter {
private var _count = 0
val count: Int get() = _count
fun increment() = _count++
}
十、总结 #
变量与常量要点:
| 关键字 | 用途 | 特点 |
|---|---|---|
val |
只读变量 | 引用不可变,优先使用 |
var |
可变变量 | 引用可变,谨慎使用 |
const val |
编译时常量 | 编译时确定值 |
lateinit |
延迟初始化 | 用于 var,非基本类型 |
lazy |
懒加载 | 用于 val,首次访问初始化 |
下一步,让我们学习 基本数据类型!
最后更新:2026-03-27