Kotlin 有一个吗?非null属性上的运算符是否阻止链中的任何NullPointerException?

Kotlin 有一个吗?非null属性上的运算符是否阻止链中的任何NullPointerException?,kotlin,kotlin-null-safety,Kotlin,Kotlin Null Safety,我无法理解Kotlin代码的以下更改: package org.example.kotlin.nulll.resolution import java.util.* object UtilResources { private var properties: Properties? = null fun loadProperties() { properties = Properties() properties?.load(UtilRes

我无法理解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”
加载的属性值(如果文件中不存在该属性)

如果我将代码更改为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.getProperties(properties)
null
,我正在用
System.out.println
语句验证它

在第一个版本中,
属性
不像在第二个版本中那样是
null
,因此
操作符是唯一改变aik的东西。但是,它被放置在非null属性之后,因此它不应该有任何效果

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


假设
config.properties
存在,并且
UtilResources.javaClass.getResourceAsStream(“/config.properties”
返回一个非空值。您可以在中找到SSCCE项目。它不包含比此问题更多的信息

请注意,我不是在寻求调试支持,我想了解正在发生的事情并扩大我对Kotlin的理解。我没有设法进一步浓缩示例


我使用的是Kotlin 1.4.31到Maven 3.6。

在您的第一个版本中,Kotlin知道您正在对可空类型调用
toString()
,因为您正在对可空字段
properties
调用
getProperty()
,因此使用了Kotlin扩展函数
Any?.toString()

在第二个版本中,Kotlin不知道您正在对可为null的类型调用
toString()
,因为您正在对不能为
null
的字段和函数
getProperty()调用
是一个不定义可空返回值的Java函数。因此,如果属性不存在,则不使用扩展函数并抛出NPE

以下代码按预期工作:

对象实用资源{
私有val属性:属性=属性()
fun loadProperties(){
load(UtilResources.javaClass.getResourceAsStream(“/config.properties”))
}
fun getProperties(键:String):String{
loadProperties()
println(属性)
println(properties.getProperty(key))
返回properties.getOptionalProperty(key).toString()
}
私有乐趣属性。getOptionalProperty(键:String):String?=getProperty(键)
}

应该没有区别,因为
?。
仅在您已将其设置为非空值的地方用于您的属性。事实上,当我运行您的第一个版本的代码时,我会得到一个NullPointerException,原因与第二个版本相同。您可能需要再次检查它。第一个版本上的NPE是否来自未命中ing
config.properties
?如果需要,可以使用。一切都在那里设置。
UtilResources.javaClass.getResourceAsStream(“/config.properties”)
返回null,因为我没有创建它。将null传递给
properties.load()
导致NPE。
?。
不会阻止您传递null。它只会阻止
属性
为null时代码运行。哎呀,我只查看了
加载属性
函数。没有意识到您在
获取属性
中询问代码。