Kotlin中非基本类型触发NullPointerException,基本类型却正常?求解
Kotlin初始化顺序引发的空指针疑惑
open class Vehicle { inner class Engine { var specs: String = "" constructor() { specs = getSpecs() } } val engine = Engine() open fun getSpecs(): String { return "" } } class Bike: Vehicle() { private val model: Model = Model("APACHE", "YAMAHA") private val year = 2024 override fun getSpecs(): String { return "Model: \${model.company} - \${model.modelName}. Year: \$year" } } data class Model( val modelName: String, val company: String )
Exception in thread "main" java.lang.NullPointerException: Cannot invoke "Model.getCompany()" because "this.model" is null
创建Bike实例时会抛出上述空指针异常,我明白异常的基本原因,但有个疑惑:如果在getSpecs方法里只保留对year的调用,去掉model.company和model.modelName的调用,程序就能正常运行。既然此时year也还没完成初始化,为什么不会触发异常?
核心原因是Kotlin中引用类型和基本数据类型的初始化默认值规则不同,再结合类的初始化顺序:
- 类初始化顺序逻辑:创建Bike实例时,会先执行父类Vehicle的初始化逻辑。父类里的
engine属性优先初始化,调用Engine的构造方法后,会触发getSpecs方法——这个方法已经被子类Bike重写,实际执行的是Bike的getSpecs实现。 - 成员变量初始化状态差异:
model是引用类型(Model对象),Kotlin中引用类型成员变量的默认初始值为null。此时调用model.company,本质是对null对象调用方法,必然触发空指针异常。year是基本数据类型(Int),Kotlin中基本数据类型的成员变量有默认初始值(Int默认值为0)。虽然此时year还没被赋值为2024,但它已经有了合法的默认值,直接使用不会出现空指针,程序可正常运行。
内容的提问来源于stack exchange,提问作者Abhilash
相关产品推荐
相关产品推荐

