是吗?非空属性上的运算符阻止链中的任何 NullPointerException?

问题描述

我无法理解对一段 Kotlin 代码的以下更改:

package org.example.kotlin.nulll.resolution

import java.util.*

object UtilResources {

    private var properties: Properties? = null

    fun loadProperties() {
        properties = Properties()
        properties?.load(UtilResources.javaClass.getResourceAsstream("/config.properties"))
    }

    fun getProperties(properties: String): String {
        loadProperties()
        System.out.println(UtilResources.properties)
        System.out.println(UtilResources.properties?.getProperty(properties))
        return UtilResources.properties?.getProperty(properties).toString()
    }
}

工作正常,即返回从 config.properties"null" 加载的属性值,以防文件中不存在该属性

如果我将代码更改为空安全

object UtilResources {

    private val properties: Properties = Properties()

    fun loadProperties() {
        properties.load(UtilResources.javaClass.getResourceAsstream("/config.properties"))
    }

    fun getProperties(properties: String): String {
        loadProperties()
        System.out.println(UtilResources.properties)
        System.out.println(UtilResources.properties.getProperty(properties))
        return UtilResources.properties.getProperty(properties).toString()
    }
}

我得到 NullPointerException,因为 UtilResources.properties.getProperty(properties)null,我正在用 System.out.println 语句进行验证。

在第一个版本中,properties 与第二个版本中的 null 不同,因此 ? 运算符是唯一改变 afaik 的东西。然而,它被放置在一个非空属性之后,所以它应该没有任何影响。

null.toString() 应该始终有效,因为它是 Kotlin 中的重载扩展函数

假设 config.properties 存在并且 UtilResources.javaClass.getResourceAsstream("/config.properties" 返回一个非空值。您可以在 https://gitlab.com/krichter-sscce/kotlin-null-resolution 找到 SSCCE 项目。它不包含比这个问题更多的信息。

请注意,我不是在寻求调试支持,我想了解正在发生的事情并拓宽我对 Kotlin 的理解。我没能进一步浓缩这个例子。

我使用的是 Kotlin 1.4.31 到 Maven 3.6。

解决方法

在您的第一个版本中,Kotlin 知道您在可空类型上调用 toString(),因为您在可空字段 getProperty() 上调用 properties,因此 Kotlins 扩展函数 {{1} } 已使用。

在您的第二个版本中,Kotlin 不知道您在 Nullable 类型上调用 Any?.toString(),因为您在一个不能为 toString() 的字段上调用 ​​getProperty() 而函数 { {1}} 是一个未定义 Nullable 返回值的 Java 函数。因此,不使用扩展函数,如果属性不存在,则抛出 NPE。

以下代码按预期工作:

null

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...