【问题标题】:Kotlin - why do I get a KotlinNullPointerExceptionKotlin - 为什么我会得到 KotlinNullPointerException
【发布时间】:2018-06-06 09:00:57
【问题描述】:

考虑以下代码:

示例

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) 在 com.series0ne.ApplicationKt.maybeWriteMessage$default(Application.kt:7) 在 com.series0ne.ApplicationKt.main(Application.kt:4)

这是因为我将message!!(null,该死!)传递给一个不可为空的参数,但是该参数永远不会被访问。

问题

为什么即使没有访问空引用,Kotlin 也会强制抛出KotlinNullPointerException

【问题讨论】:

  • 您通过取消引用来访问它:!!

标签: kotlin


【解决方案1】:

message: String? 表示message 可能是也可能不是null

由于您的函数maybeWriteMessagemessage 具有默认值null,并且您在没有指定message 的情况下调用maybeWriteMessage() - 调用writeMessage(message!!) 时将使用默认值(null) .

正如documentation 中所写,!! 运算符在值为null 时会引发异常。

安全触发writeMessage 的一种方法是使用.let

fun maybeWriteMessage(message: String? = null) {
    message?.let { 
      writeMessage(it)
    }
}

【讨论】:

【解决方案2】:

如果message 为空,运算符!! 将抛出KotlinNullPointerException

你可以在这里阅读: https://kotlinlang.org/docs/reference/null-safety.html#the--operator

【讨论】:

  • 从 Kotlin 1.4 开始,异常将改为 NullPointerException(不同的类型),请参阅 here。因此,如果任何代码明确捕获 KotlinNullPointerException(不鼓励这样做),那么升级到 1.4 将是一个重大更改
【解决方案3】:

在以下代码中:

fun maybeWriteMessage(message: String? = null) {
    writeMessage(message!!)
}

您通过使用!!(非空断言运算符)断言可空参数message 不为空。如果message 为空,这将抛出一个空指针。

TL;DR:除非您确切知道自己在做什么,否则不要使用!!。几乎总是有更好的方法。

!!运营商

第三个选项适用于 NPE 爱好者非空断言运算符 (!!) 将任何值转换为非空类型并在以下情况下抛出异常 值为空。我们可以写 b!!,这将返回一个非空值 b 的值(例如,我们示例中的字符串),如果 b 是,则抛出 NPE 空:

val l = b!!.length

因此,如果你想要一个 NPE,你可以拥有它,但你必须要求它 明确地,并且它不会突然出现。

【讨论】:

    【解决方案4】:

    来自the documentation

    !!运营商

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

    val l = b!!.length

    因此,如果你想要一个 NPE,你可以拥有它,但是你 必须明确要求它,它不会突然出现。

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

    【讨论】:

      猜你喜欢
      • 2018-12-29
      • 1970-01-01
      • 2012-02-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-05-21
      • 1970-01-01
      相关资源
      最近更新 更多