请考虑以下代码:
示例
fun main(args: Array<String>) {
maybeWriteMessage()
}
fun maybeWriteMessage(message: String? = null) {
writeMessage(message!!)
}
fun writeMessage(message: String) {
println("Hello World")
}
输出
线程“main”中的异常kotlin.KotlinNullPointerException at com.series0ne.ApplicationKt.maybeWriteMessage(Application.kt:8)at com.series0ne.ApplicationKt.maybeWriteMessage $默认(Application.kt:7) 在com.series0ne.ApplicationKt.main(Application.kt:4)
这是因为我将message!!
(null,该死的!)传递给一个不可为空的参数,但是从不访问该参数。
问题
为什么即使没有访问空引用,Kotlin也会强行抛出KotlinNullPointerException
?
答案 0 :(得分:9)
message: String?
表示message
可能是null
,也可能不是maybeWriteMessage
。
由于您的null
函数的message
默认值为maybeWriteMessage()
,而您正在调用message
而未指定null
- 默认值({{调用writeMessage(message!!)
时将使用1}}}。
如documentation中所述,!!
- 运算符在值null
时抛出异常。
安全触发writeMessage
的一种方法是使用.let
:
fun maybeWriteMessage(message: String? = null) {
message?.let { nonNullMessage ->
writeMessage(nonNullMessage)
}
}
答案 1 :(得分:3)
如果!!
为空,则运营商KotlinNullPointerException
会抛出message
。
你可以在这里阅读: https://kotlinlang.org/docs/reference/null-safety.html#the--operator
答案 2 :(得分:3)
在以下代码中:
fun maybeWriteMessage(message: String? = null) {
writeMessage(message!!)
}
通过使用message
(非空断言运算符)断言可空参数!!
不为空。如果message
为null,则会抛出空指针。
TL; DR:除非你确切知道自己在做什么,否则不要使用!!
。几乎总有一种更好的方式。
!!操作者强>
第三个选项适用于 NPE爱好者:非空断言运算符 (!!)将任何值转换为非null类型,如果,则抛出异常 值为null。我们可以写b !!,这将返回一个非null b的值(例如,在我们的例子中是一个字符串)或者如果b是,则抛出一个NPE 空:
val l = b!!.length
因此,如果你想要一个NPE ,你可以拥有它,但你必须要求它 明确地说,它并不是出乎意料的。
答案 3 :(得分:1)
!!操作者强>
第三种选择适用于NPE爱好者:非空 断言运算符(!!
)将任何值转换为非null类型 如果值为null,则抛出异常。我们可以写b!!
,这个 将返回b
的非空值(例如,在我们的示例中为String
)或 如果b
为空,则抛出NPE:
val l = b!!.length
因此,如果你想要一个NPE,你可以拥有它,但是你 必须明确地要求它,并且它不会出现在蓝色之外。
因此,无论您的函数是否使用参数,使用message!!
,您都明确要求使用NPE。