【8】Kotlin 之 lateinit关键字 与lazy

前言

lateinit是许多刚进入学习kotlin常常会掉入的坑之一。很多人为了保证java原有的语法,在定义变量和对象的过程中,会使用如下的定义方式。

class Demo{
	private var value: String

	fun printValue(){
		println(value)
	}
}

这个时候,编译器就会提示错误

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

然后有很多小伙伴解决问题,会使用提示符快捷键按钮自动修复这个问题,结果发现在定义变量的位置多了一个lateinit关键字

private lateinit var value: String

编译器的问题就这样躲避过去了,可是运行的过程,还是发生了异常问题。

原理

lateinit修饰属性的时候,实际上就是表示,这个属性初始化的时机和方式,由开发者自己决定。而编译器在编译kotlin语言的过程中,会将lateinit修饰属性的所有调用位置都做一个非空的检查判断,然后抛出异常。
// 字节码等价代码

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

你定义value属性的值确实为null,但由于给定value的类型为String类型,而kotlin当中String类型是不允许容纳null,kotlin为了保证“绝对的空安全性”,所以只能抛出异常。

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

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

其他的初始化方式,慎用。

拓展

既然说到lateinit,那可以提一下kotlin中另一个常用的lazy。lazy并不是kotlin中的关键字,而是一个顶层函数,点击lazy跳转,可以看到lazy内部实现是通过高阶函数的方式。
tip:这里提到的顶层函数 和 高阶函数 就不做拓展了,想要了解的可以通过资料自行了解。

val b by lazy{
	// ...
}

// LazyJVM.kt
public actual fun <T> lazy(initializer: () -> T): Lazy<T> = SynchronizedLazyImpl(initializer)

先说一下lazy的作用,顾名思义是懒加载的意思。懒加载这个词,估计很多开发者都不会陌生,我第一次听到懒加载是在viewpage + fragment的使用当中,通过懒加载的方式来减少加载数据时产生的内存消耗。而kotlin中的lazy,则是当b这个这个属性第一次被使用的时候,就会去初始化b这个对象,lazy后面跟的时一个lambda表达式,最后一行作为返回对象赋值给b。

lazy 和 lateinit

  1. lateinit 表示对全局变量进行延迟初始化,这样就不用一开始的时候将他赋值为null了。
  2. lazy 表示当调用该属性时,会执行该lazy内部的getValue()函数,而getValue()方法又会调用到lazy函数传入的lambda表达式,这样表达式的代码就可以得到执行。
  • 5
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值