Kotlin刨根问底(一):你真的了解Kotlin中的空安全吗?(下)

简介: 行文结构:要点提炼(方便回顾) + 常规操作 + 源码层面摸索实现原理, 内容部分摘取自:《Kotlin实用指南》

0x3、不是绝对的空指针安全


如题,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)
}


运行结果如下



Tips:也可以为Java代码@NotNull注解来解决~


0x4、Kotlin是如何实现空安全的


接着我们来探究下,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中对空安全背后的处理套路如下:


  • 1、非空类型的属性编译器添加@NotNull注解,可空类型添加@Nullable注解;


  • 2、非空类型直接对参数进行判空,如果为空直接抛出异常;


  • 3、可空类型,如果是?.判空,不空才执行后续代码,否则返回null;如果是!!,空的话直接抛出NPE异常。


  • 4、as操作符会判空,空的话直接抛出异常,不为空才执行后续操作,没做类型判断!运行时可能会报错!


  • 5、as?则是新建一个变量,参数赋值给它,然后判断是否为特定类型,赋值为null,接着把这个变量的值赋值给另一个新的变量,这里有一点注意:as?处理后的参数可能为空!!!所以调用as?转换后的对象还需要添加安全调用操作符(?.)


提醒:(这里直接用编译后Java代码的原因是比较直观~)


  • @NotNull注解对应字节码里的:@Lorg/jetbrains/annotations/NotNull;


  • @Nullable注解对应字节码里的:@Lorg/jetbrains/annotations/Nullable;


参考文献:



相关文章
|
4月前
|
安全 Java 编译器
深入浅出:Kotlin 中的空安全机制
【8月更文挑战第31天】
74 0
|
6月前
|
安全 Kotlin
Kotlin中的安全导航操作符?.、空合并运算符?:以及let函数的实践与理解
Kotlin中的安全导航操作符?.、空合并运算符?:以及let函数的实践与理解
|
安全 Java Kotlin
Kotlin中空安全操作符,异常处理和自定义异常,以及先决条件函数详解
Kotlin中空安全操作符,异常处理和自定义异常,以及先决条件函数详解
141 0
|
安全 IDE JavaScript
From Java To Kotlin:空安全、扩展、函数、Lambda很详细,这次终于懂了
Kotlin 是什么? 可以做什么? Android 官方开发语言从Java变为Kotlin,Java 有哪些问题? Kotlin的优点 Kotlin 特性(Features)
11588 1
From Java To Kotlin:空安全、扩展、函数、Lambda很详细,这次终于懂了
|
安全 Java 编译器
Kotlin学历之空安全
Kotlin学历之空安全
104 0
Kotlin学历之空安全
|
安全 Java 编译器
【Kotlin 初学者】空安全与异常
在Java中,定义一个变量可以默认不赋值,因为Java的系统会给我们默认赋一个默认值,并且Java可定义一个赋值为null的变量,这样在使用这个变量的时候都会去显示判断该变量是否为null。这使得在Java中我们司空见惯的空指针异常NullPointerException,带给了我们很多麻烦。
380 0
【Kotlin 初学者】空安全与异常
|
安全 Java Kotlin
Kotlin刨根问底(一):你真的了解Kotlin中的空安全吗?(上)
行文结构:要点提炼(方便回顾) + 常规操作 + 源码层面摸索实现原理, 内容部分摘取自:《Kotlin实用指南》
213 0
|
2月前
|
JSON 调度 数据库
Android面试之5个Kotlin深度面试题:协程、密封类和高阶函数
本文首发于公众号“AntDream”,欢迎微信搜索“AntDream”或扫描文章底部二维码关注,和我一起每天进步一点点。文章详细解析了Kotlin中的协程、扩展函数、高阶函数、密封类及`inline`和`reified`关键字在Android开发中的应用,帮助读者更好地理解和使用这些特性。
40 1
|
3月前
|
Android开发 开发者 Kotlin
告别AsyncTask:一招教你用Kotlin协程重构Android应用,流畅度飙升的秘密武器
【9月更文挑战第13天】随着Android应用复杂度的增加,有效管理异步任务成为关键。Kotlin协程提供了一种优雅的并发操作处理方式,使异步编程更简单直观。本文通过具体示例介绍如何使用Kotlin协程优化Android应用性能,包括网络数据加载和UI更新。首先需在`build.gradle`中添加coroutines依赖。接着,通过定义挂起函数执行网络请求,并在`ViewModel`中使用`viewModelScope`启动协程,结合`Dispatchers.Main`更新UI,避免内存泄漏。使用协程不仅简化代码,还提升了程序健壮性。
115 1
|
5月前
|
安全 Android开发 Kotlin
Android经典面试题之Kotlin延迟初始化的by lazy和lateinit有什么区别?
**Kotlin中的`by lazy`和`lateinit`都是延迟初始化技术。`by lazy`用于只读属性,线程安全,首次访问时初始化;`lateinit`用于可变属性,需手动初始化,非线程安全。`by lazy`支持线程安全模式选择,而`lateinit`适用于构造函数后初始化。选择依赖于属性特性和使用场景。**
183 5
Android经典面试题之Kotlin延迟初始化的by lazy和lateinit有什么区别?