如何在Kotlin中使用by关键字初始化lateinit变量?
先搞懂核心问题
lateinit 和 by 关键字(属性委托)是Kotlin里两种完全不同的属性初始化机制,根本不能混用:
lateinit var是用来标记非空的可变变量,告诉编译器“我后面会手动初始化它”,编译器就不会因为变量没初始化报错。by是把属性的读写逻辑交给另一个对象(委托)处理,属性的初始化、获取、修改全由委托说了算。
这俩逻辑冲突,所以编译器绝对不允许你在lateinit var后面加by,也不能在函数里对lateinit变量写test by something {}这种代码——by只能在声明属性的时候用,不是用来赋值的。
给你俩解决方案,看需求选
要是属性只读,直接用by lazy就行
如果你的变量不需要修改(用val),根本不用lateinit,直接上by lazy,第一次访问的时候自动初始化:
val test: Int by lazy { // 这里写初始化逻辑,比如算个值、读个文件都行 100 } fun main() { println(test) // 第一次调用才执行lazy里的代码,初始化后就复用这个值 }
要是属性需要可变,自己写个委托类模拟lateinit
如果必须是可变的var,又要延迟初始化,那得自己写个简单的委托类,实现和lateinit一样的效果:
import kotlin.properties.ReadWriteProperty import kotlin.reflect.KProperty // 自定义委托,模拟lateinit的行为 class LateinitVar<T> : ReadWriteProperty<Any?, T> { private var value: T? = null override fun getValue(thisRef: Any?, property: KProperty<*>): T { return value ?: throw UninitializedPropertyAccessException("属性${property.name}还没初始化呢") } override fun setValue(thisRef: Any?, property: KProperty<*>, value: T) { this.value = value } } // 用这个委托声明变量 var test: Int by LateinitVar() fun main() { // println(test) // 这行放开会报错,因为还没初始化 test = 200 // 手动赋值初始化 println(test) // 正常输出200 }
这个自定义委托和lateinit var的表现一模一样:没初始化就访问会抛出异常,赋值后就能正常读写。
顺便纠正你示例里的小错误
- Kotlin的基本类型首字母要大写,
int得改成Int; by只能在声明属性的时候用(比如var test: Int by ...),不能在函数里对着变量写test by something {},这语法本身就不对。
内容的提问来源于stack exchange,提问作者recsater
相关产品推荐
相关产品推荐

