Kotlin - 为什么我会得到一个KotlinNullPointerException

时间:2018-06-06 09:00:57

标签: kotlin

请考虑以下代码:

示例

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

4 个答案:

答案 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)

来自the documentation

  

!!操作者   

第三种选择适用于NPE爱好者:非空   断言运算符(!!)将任何值转换为非null类型   如果值为null,则抛出异常。我们可以写b!!,这个   将返回b的非空值(例如,在我们的示例中为String)或   如果b为空,则抛出NPE:

     

val l = b!!.length

因此,如果你想要一个NPE,你可以拥有它,但是你   必须明确地要求它,并且它不会出现在蓝色之外。

因此,无论您的函数是否使用参数,使用message!!,您都明确要求使用NPE。