Kotlin学习记录
笔者就职的小组近日正筹备新项目,预备在新项目中引入kotlin以便适配之后Google的各种新框架或特性等(如jetpack compose就是使用kt),而且个人认为kt的空安全特性有利于降低项目的维护难度与提高应用的稳定性,在此记录一下自己的入坑之旅。
Kotlin变量声明与类型判断
kt不需要显示地声明变量类型,而是类似flutter的声明语法以赋值的类型判断,以var/val替代原声明变量的位置,需要声明类型则是在变量名后加“:Class”,而且摒弃final关键字,以val替代其功能,即val实际上是“final var”;这里需要明确final关键字其实是非常优秀的一个关键字,其表示的之后值不可变或指向对象不可变可以极大地减轻我们阅读理解代码的难度,但诚然不少开发者觉得加个final“工作量加大”就较少使用,val就是解决这“工作量加大”的问题。
val str1 = "hello"
val str2: String = "hello again" // 可选择是否声明变量类型
var str3 = "hello where"
val str4 = "hello here"
str3 = "hello again" // str3是var允许多次赋值或修改指向对象
str4 = "bye" // str4是val只允许一次赋值,因而该行代码在IDE内会飘红报错
kotlin空安全
应该不少同学都在项目中遇到过外网报出的空指针crash,我们通常最直接了当的操作就是直接加一层如下的空判断,这的确非常有效,但是项目中必然不止两三个这种场景,各种监听回调的注销都加上这么一个空判断,安全是安全,丑也是真的丑,因此kt的空安全就很好地解决了这个烦恼
if (mImpController !== null) {
mImpController.released();
}
Kotlin将变量类型分为不可为空与可能为空两种(我们开发时尽量采用前者),默认的类型声明就是不可能为空,只有在声明时在变量名后添加“?”才表示可以为空,(感觉这有点像 int szBoy = (jmBoy == null ? null : 1); ,如果没有问号就没有这个机会)。对于不可为空的变量便可以直接调用方法而不用担心发生空指针crash,因为它必不为null这个不难理解;而对于可能为空的变量,调用方法前它必须添加“?”或者“!!”来检查当前变量不为null才会往下执行方法,“?”是为null不调用,“!!”则是为null抛异常Illegalstateexception,可以理解为前者用于外网业务场景,后者用于调试定位问题,这样一来,上述的场景在kt的写法如下,简洁大气
// 假设mImpController为可能为空的变量
var mImpController: ImpController? = ImpController
fun destroy() {
mImpController?.released();
}
这时可能有的同学会引出一个疑问,如果一个可空对象因为为null而没有执行对应方法,那么原本用于承接该方法返回值的变量应该是什么类型呢?好像有点僵硬,下面举个例子,看完代码大家应该明白kotlin的可空传递性是什么含义了。
fun test() {
var mNonnullField: Int = mImpController?.getInt(); // 编译失败,类型不正确
var mNullableField: Int> = mImpController?.getInt(); // 编译成功
}
But 作为android开发,我们常常对一个activity做初始化时是在onCreate中进行,也就是说可能无法对成员变量在声明阶段就完成赋值,这对于默认非空的kotlin变量声明就有些许尴尬了,对此kotlin 的解决办法是引入latinit关键字,功能如名——“延迟初始化”,这就需要我们开发者自己把握其调用时机了,要保证调用时该变量已经完成初始化,but but总的来说这种类型的场景依然优于java代码处处判空的操作,而且基本只需防止activity在onCreate阶段crash导致未完成初始化就走onDestroy的场景,对此kotlin也提供了lateinit专属的isInitialized方法判断其有无完成初始化。