首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >【错误记录】Kotlin 代码运行时报错 ( 在 init 初始化块中调用还未初始化的成员属性 )

【错误记录】Kotlin 代码运行时报错 ( 在 init 初始化块中调用还未初始化的成员属性 )

作者头像
韩曙亮
发布2023-03-30 18:53:22
发布2023-03-30 18:53:22
2.5K0
举报

文章目录

该问题的本质就是 , 成员属性 在 init 初始化代码块中进行初始化 , 但是在初始化之前调用了该 成员属性 , 编译时没有报错信息 , 但是运行时会报异常 ;

一、报错信息


执行如下代码 :

代码语言:javascript
复制
class Hello {
    var name: String
    fun nameFirstLetter() = name[0]
    init {
        println(nameFirstLetter())
        name = "Tom"
    }
}

fun main() {
    Hello()
}

执行结果 :

代码语言:javascript
复制
Exception in thread "main" java.lang.NullPointerException
	at Hello.nameFirstLetter(Hello.kt:3)
	at Hello.<init>(Hello.kt:5)
	at HelloKt.main(Hello.kt:11)
	at HelloKt.main(Hello.kt)

Process finished with exit code 1

上述代码在编译时 , 没有报错 ;

二、问题分析


从 初始化 角度分析 上述代码的执行顺序 , Kotlin 类 对象在实例化 时会执行一系列的 初始化操作 , 这些操作按照如下顺序执行 :

  • 主构造函数 中属性赋值
  • 类中的属性赋值
  • init 初始化块 中的代码执行
  • 次构造函数 中的代码执行

首先 , 上述代码中没有主构造 函数 , 因此该项忽略 ;

然后 , 执行属性的赋值 , 代码中定义了 name 属性 , 但是没有进行赋值 ;

代码语言:javascript
复制
var name: String

再后 , 执行 init 初始化块 , 其中先执行 nameFirstLetter 函数 , 在该函数中调用了 fun nameFirstLetter() = name[0] 中的 name 属性 , 但是 name 属性还没有赋值 , 因此爆出了空指针异常 ;

代码语言:javascript
复制
    init {
        println(nameFirstLetter())
        name = "Tom"
    }

该问题的本质就是 , 成员属性 在 init 初始化代码块中进行初始化 , 但是在初始化之前调用了该 成员属性 , 编译时没有报错信息 , 但是运行时会报异常 ;

三、解决方案


调换 初始化代码块 中的代码顺序 , 先给 name 成员赋值 , 然后再执行 调用 name 成员的方法 ;

代码语言:javascript
复制
class Hello{
    var name: String
    fun nameFirstLetter() = name[0]
    init {
	    name = "Tom"
        println(nameFirstLetter())
    }
}

fun main() {
    Hello()
}
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2023-01-19,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 文章目录
  • 一、报错信息
  • 二、问题分析
  • 三、解决方案
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档