Kotlin 有一个吗?非null属性上的运算符是否阻止链中的任何NullPointerException?
我无法理解Kotlin代码的以下更改: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
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是否来自未命中ingconfig.properties
?如果需要,可以使用。一切都在那里设置。UtilResources.javaClass.getResourceAsStream(“/config.properties”)
返回null,因为我没有创建它。将null传递给properties.load()
导致NPE。?。
不会阻止您传递null。它只会阻止属性
为null时代码运行。哎呀,我只查看了加载属性
函数。没有意识到您在获取属性
中询问代码。