最近挺长一段时间,Flutter相关的技术文章和讨论各类刷屏,而我:前端
摸鱼挺长一段时间,折腾了不少花里胡哨的东西,最近打算重拾Android开发的老本行,广度 -> 深度,好好复习几个月,准备Android面试,尽管常常有人调侃:android
每一个人的时间都是有限的,一旦作出学习某块知识的选择,意味着付出了暂时没法学习其余知识的机会成本,须要取舍。不可能等什么都学会了再去面试,学完得猴年马月,并且技术,是学不完的…
如何在有限时间内效益最大化,选择学什么显得尤其重要,看下掘金Android类的TAG:web
排行第一的是Flutter和Kotlin,二者的区别,在《Kotlin 和 Flutter 对于开发者究竟意味着什么?》中的描述:面试
Flutter和Kotlin并不冲突!apache
- Kotlin可解读为:Android逐渐放弃Java这个开发依赖。
- Flutter则可解读为:Google 开始放弃 Android,迎接新操做系统 Google Fuchsia的准备。
接着二选一咯,具体学哪一个,仍是看市场需求,拉钩随手搜下Flutter和Kotlin的岗位需求:编程
其中一则Flutter岗的任职要求:安全
可能作过RN和前端的开发仔更适合学Flutter吧~app
行吧,仍是作回原生开发仔,Android原生开发,愈来愈多的公司加上「熟悉Kotlin」这条招聘要求,被如火如荼的Flutter浪潮淹没,你们可能都忘了,在今年五月的Google I/O大会上,官方曾宣布:「Kotlin编程语言是Android应用开发的首选语言」!编程语言
初次接触Kotlin已经是三年前,在上家公司用Kotlin重构了平板的应用市场和电台APP。说来惭愧,至今仍是一个API选手,不过相信在座不少Android开发和我同样,都停留在会用的程度。函数
不想止步于会用,还想了解下原理,因此有了这个系列。本节先来刨一刨Kotlin中的空安全~
NullPointerException(NPE),空指针异常,在Java开发时,若是不想遇到这种异常,须要在使用前不停地判断它是否为Null。而在Kotlin中是空安全的,在编译期就处理Null,以此避免执行时异常。另外空安全不是Kotlin特有的,其余不少的变成语言也有,接着简单描述下Kotlin空安全的相关用法。
Kotlin中经过「非空类型」和「可空类型」来规避空NPE,非空类型不能设置为Null值:
可空类型能够设置为Null值,在类型后加上 可空操做符(?) 便可,代码示例以下:
可空类型,直接访问它的属性或方法,会报错:
能够经过 安全调用操做符(?.) 或 非空断言运算符(!!) 来解决,代码示例以下:
运行结果以下:
三目条件运算符的简略写法:若是不是空,就返回它,不然返回另外一个值。代码示例以下:
Kotlin中可使用as
关键字来进行类型转换,而使用as?
表示安全类型的转换。最多见的使用场合,后台接口返回一个参数,须要咱们本身作下类型转换,直接用as的话,若是参数为null或者非String类型,就可能引起异常,若是用as? ,参数异常则不会转换,代码示例以下:
运行结果以下:
let函数除了可用于在同一个做用域下操做变量外(代码更优雅)外:
tvTitle.let {
it.text = "标题"
it.textSize = 18.0f
it.gravity = Gravity.LEFT or Gravity.CENTER
it.setOnClickListener {}
}
复制代码
还能够用做作判null操做,好比下面这样的代码:
test咱们已经设置了一个值,可是仍是报错,添加上一个非空断言便可:
还有个更优雅的写代码方式,就是用?.let{},修改后的代码以下:
另外?.let{}遍历集合会忽略null值,只对非null值执行操做;除此以外,还能够用集合操做函数filterNotNull过滤出非空元素。
如题,Kotlin中并非绝对的空指针安全,最多见的就是在Kotlin去调Java代码,好比下面这个例子:
//Java
public class Test {
public static String getMsg() {
return null;
}
}
//Kotlin
fun main() {
println(Test.getMsg().length)
}
复制代码
运行后就直接报错:
当你与Java代码进行互操做时,Null安全性确实被破坏了,固然想规避这个问题也很简单,加个?便可,示例以下:
fun main() {
println(Test.getMsg()?.length)
}
复制代码
运行结果以下:
接着咱们来探究下,Kotlin中究竟是怎么实现空安全的,写下简单的代码:
fun test_1(str: String) = str.length
fun test_2(str: String?) = str?.length
fun test_3(str: String?) = str!!.length
fun test_4(str: Any?) { str as String }
fun test_5(str: Any?) { str as? String }
复制代码
接着依次点击:Tools -> Kotlin -> Show Kotlin Bytecode,生成字节码:
生成后的Java代码以下:
接着分析一波,首先是test_1函数,能够看到这里有一个@NotNull的注解,而后是:
Intrinsics.checkParameterIsNotNull(str, "str");
复制代码
Intrinsics是Kotlin的一个内部类,定位到checkParameterIsNotNull函数:
再跟:
行吧,其实就是直接对参数判空,若是为空抛出参数为空的异常。接着看下test_2函数,比较简单,判断是否为空,不为空的话,调用对应的方法,不然返回一个null。再接着是test_3函数,直接判断是否为空,空的话直接抛出Npe异常。
而后是test_4函数,判空,若是空抛出类型转换异常,不然执行后续代码;最后是test_5函数,建立一个新对象把参数的值传给他,而后进行类型判断,若是不是特定类型,对象赋值null,而后把执行类型强转后的对象赋值给一个新的对象。
综上,Kotlin中对空安全背后的处理套路以下:
- 一、非空类型的属性编译器添加@NotNull注解,可空类型添加@Nullable注解;
- 二、非空类型直接对参数进行判空,若是为空直接抛出异常;
- 三、可空类型,若是是?.判空,不空才执行后续代码,不然返回null;若是是!!,空的话直接抛出NPE异常。
- 四、as操做符会判空,空的话直接抛出异常,不为空才执行后续操做,没作类型判断!运行时可能会报错!
- 五、as?则是新建一个变量,参数赋值给它,而后判断是否为特定类型,赋值为null,接着把这个变量的值赋值给另外一个新的变量,这里有一点注意:as?处理后的参数可能为空!!!因此调用as?转换后的对象还须要添加安全调用操做符(?.)
提醒:(这里直接用编译后Java代码的缘由是比较直观~)
- @NotNull注解对应字节码里的:@Lorg/jetbrains/annotations/NotNull;
- @Nullable注解对应字节码里的:@Lorg/jetbrains/annotations/Nullable;
以上就是本人关于Kotlin中空安全实现原理的解读,若是纰漏或建议,欢迎在评论区指出,谢谢~
参考文献:
若是本文对你有所帮助,欢迎
留言,点赞,转发
素质三连,谢谢😘~