大家好,我是青空。今天给大家带来的是kotlin NPE方案。
文末可领取大厂面试题
NPE的来源
显式调用 throw NullPointerException()
使用了 !! 操作符
-
这是Kotlin提供的用户可强制抛出NPE的操作符
-
使用了!!只要碰到NPE就会如期抛出
有些数据在初始化时不一致
-
this泄漏
-
未初始化的this被传递,并用于其他地方
-
调用了一个 超类中的open成员,并在 派生类中使用了 该open成员的未初始化 状态
Java 互操作
-
企图访问平台类型的 null 引用的成员
-
平台类型 即 Java 声明的类型
-
java的引用可能是null
-
平台类型的范例
val list = ArrayList<String>() // 非空(构造函数结果)
list.add("Item")
val size = list.size // 非空(原生 int)
val item = list[0] // 推断为平台类型(普通 Java 对象)
item.substring(1) // 允许,如果 item == null 可能会抛出异常
-
具有错误可空性的 Java 互操作的泛型类型
-
真是绕口,怎么理解呢
-
从java代码中向Kotlin添加了一个null值到MutableList
-
MutableList无法处理null
-
自然这个null需要MutableList<String?>处理
-
由外部 Java 代码引发的其他问题
如何区分类型系统是否容忍null
范例
fun main() {
var a: String = "abc"
a = null // 编译错误
}
若 a 声明为String! 则 可为空
fun main() {
var b: String? = "abc"
b = null // ok
print(b)
}
-
访问 val l = a.length
-
这就不会报错
-
访问val l = b.length // 错误:变量“b”可能为空
-
编译器会报错
在条件中检测 null
这就是用if …else进行判空
范例
val l = if (b != null) b.length else -1
安全的调用
操作符,写作 ?.
会议一下java的网络请求返回的实体
-
在java中是这样的
-
只要有一个环节为null就报npe
-
bob.department.head.name
-
在Kotlin中可以这样
-
任一环节为null,就会返回 null
-
bob?.department?.head?.name
如果要只对非空值执行某个操作
- 可以与 let 一起使用 范例
fun main() {
val listWithNulls: List<String?> = listOf("Kotlin", null)
for (item in listWithNulls) {
item?.let { println(it+" is the result") } // 输出 Kotlin 并忽略 null
}
}
输出
Kotlin is the result
赋值过程中的安全调用
范例
// 如果 `person` 或者 `person.department` 其中之一为空,都不会调用该函数:
person?.department?.head = managersPool.getManager()
在这里范例中,只要左侧返回null,就跳过右侧表达式的求值
注意
不要在右侧表达式做过多的处理,尽量纯净,小心处理会依赖这部分逻辑的操作,避免埋坑
Elvis 操作符
当我们有一个可空的引用 r 时,我们可以说“如果 r 非空,我使用它;否则使用某个非空的值 x”
一般是这样写的
val l: Int = if (r != null) r.length else -1
通过 Elvis 操作符表达
-
写作 ?:
-
这个表达式,就可以改写为
-
val l = r?.length ?: -1
-
?: 左侧表达式非空,?: (elvis 操作符)就返回其左侧表达式,否则返回右侧表达式
-
注意
-
throw 和 return 在 Kotlin 中都是表达式
-
在表达式中也支持throw和return
范例
fun foo(node: Node): String? {
val parent = node.getParent() ?: return null
val name = node.getName() ?: throw IllegalArgumentException("name expected")
// ……
}
!! 操作符
如果你想要一个 NPE
- 你必须显式要求它
就用到!!操作符
范例
val l = b!!.length
b为null的话,就会强制抛出NPE
安全的类型转换
对象不是目标类型
- 常规类型转换可能会导致 ClassCastException
可以选择as?
- 进行安全类型转换
val aInt: Int? = a as? Int
转换不成功则返回 null
可空类型的集合
你有一个可空类型元素的集合
- 你想要过滤非空元素
可以使用 filterNotNull
范例
val nullableList: List<Int?> = listOf(1, 2, null, 4)
val intList: List<Int> = nullableList.filterNotNull()
最近又赶上跳槽的高峰期,好多粉丝,都问我有没有最新大厂面试题,我连日加班好多天,终于整理好了,1000+ 道,20多份大厂面试题大全,我会持续更新中!公众号回复【面试题】即可获取。