kotlin lateinit

有的小伙伴刚开始写 Kotlin 代码的时候,会把写 Java 代码的习惯也带过来,比如这样:

class Demo {
  var value: String
  
  fun printValue() {
    println(value)
  }
}

当然,这样写的后果就是一个编译错误:

Error:(2, 5) Kotlin: Property must be initialized or be abstract

这时候,有的小伙伴看到了 lateinit 修饰符

lateinit var value: String

一编译,哇,没有错误呢~ 测试一下吧

fun main(args: Array<String>) {
  val d = Demo()
  d.printValue()
}

运行!

Exception in thread "main" kotlin.UninitializedPropertyAccessException: lateinit property value has not been initialized

怎么回事?仔细看看错误信息:异常是 UninitializedPropertyAccessException,好像是“访问未初始化的属性异常”,后面的错误信息说“使用 lateinit 修饰的属性 value 未初始化”……

What the f**k,难道 value 的值不会默认为 null 吗?垃圾 Kotlin!!!

lateinit 是一个坑,对于萌新来说还是一个不小的坑。

当我们用 lateinit 修饰类属性的时候,实际上在告诉编译器:这个属性的初始化的时机和方式由我亲自把控,你个垃圾编译器哪儿凉快哪儿待着去。

但可爱的 Kotlin 编译器不能坐视你把 null 赋给非空的 String 类型呀,很贴心地把这个类里所有访问 lateinit 属性的地方都做了一次空检查:

// 字节码等价代码

fun printValue() {
  val tempValue = this.value
  if(tempValue == null) {
    throw UninitializedPropertyAccessException("lateinit property value has not been initialized")
  }
  println(tempValue)
}

没错,你定义的 value 属性确实是 null,但因为你给 Kotlin 的类型是 String,不能容纳 null,Kotlin 为了保证“绝对的空安全”,只能抛出异常了事。这个锅是谁的?编译器当然一脸无辜:肯定是你的,谁让你用 lateinit 呢?年轻人呐,自由是有代价的,你用 lateinit 获得了片刻的自由,得到的却是无尽的异常,这个道理,你明白了吗?

回到正题,lateinit 的蛋疼之处在于,萌新以为找到了接近 Java 的写法,但实际上一只脚已经踩在了地雷上;有一定 Kotlin 经验的同学呢,要么觉得 lateinit 给的自由度完全不够,必要的时候直接 “var + 可空类型”浪起,要么处处担惊受怕,生怕碰到没有初始化的属性。这样,lateinit 就变成一个十足的鸡肋了,会用的不想用,不会用的处处掉坑。

对于 Kotlin 新手来说,应该抛开 Java 式的写法,牢记类属性的三种初始化方式:

主构造函数内定义属性,使用传入的参数初始化属性;
类体内定义属性,同时初始化;
类体内定义属性,init 块里初始化。
其他的初始化方式,慎用。

转自:在 Kotlin 代码中慎用 lateinit 属性

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值