Java 科特林:为什么会这样!!为jvm编译时,运算符是否生成空检查?

Java 科特林:为什么会这样!!为jvm编译时,运算符是否生成空检查?,java,jvm,kotlin,Java,Jvm,Kotlin,我用它来检查Kotlin生成的字节码。我发现无论什么时候!!运算符,则生成相应的空检查。例如,对于以下kotlin代码: fun main(args: Array<String>) { var a : Int? = null; println(a!!+2) } 我的问题是:为什么需要生成空检查。JVM在遇到空接收器上的方法调用时不会抛出NPE吗?为什么需要另一个冗余检查?我只看到一个原因:字符串操作 val s = null; val s2 = "abc" + s;

我用它来检查Kotlin生成的字节码。我发现无论什么时候!!运算符,则生成相应的空检查。例如,对于以下kotlin代码:

fun main(args: Array<String>) {
    var a : Int? = null;
    println(a!!+2)
}

我的问题是:为什么需要生成空检查。JVM在遇到空接收器上的方法调用时不会抛出NPE吗?为什么需要另一个冗余检查?

我只看到一个原因:字符串操作

val s = null;
val s2 = "abc" + s;     // abcnull
val s3 = "abc" + s!!;   // NPE

我只看到一个原因:字符串操作

val s = null;
val s2 = "abc" + s;     // abcnull
val s3 = "abc" + s!!;   // NPE

问题是JVM不能足够早地抛出NPE。您并不总是立即使用非null类型。使用null断言可以防止null在代码中传播得太远而无法跟踪。假设你有这门课

class Foo {
    var bar : Bar = null
    fun foo() {doSomethingWitNonNullBar(bar)}
}

在这里,在Foo中设置后不会立即使用该条。如果您意外地编写了foo.bar=null之类的内容,并在另一个线程上调用了foo.whoolater,那么很难知道这个null来自何处。这可能看起来很愚蠢,但当您的代码混合了许多可空类型和非空类型时,它将很快成为一个真正的交易。如果没有断言,您就无法确定类型是否为null。

问题在于JVM不能足够早地抛出NPE。您并不总是立即使用非null类型。使用null断言可以防止null在代码中传播得太远而无法跟踪。假设你有这门课

class Foo {
    var bar : Bar = null
    fun foo() {doSomethingWitNonNullBar(bar)}
}
在这里,在Foo中设置后不会立即使用该条。如果您意外地编写了foo.bar=null之类的内容,并在另一个线程上调用了foo.whoolater,那么很难知道这个null来自何处。这可能看起来很愚蠢,但当您的代码混合了许多可空类型和非空类型时,它将很快成为一个真正的交易。如果没有断言,则无法确定类型是否为null。

的语义!!表达式表示它在!!运算符,并抛出特定类型的异常KotlinNullPointerException,如果要检查的表达式为null,则该异常是标准NullPointerException的子类。抛出一个特定的异常子类表明异常是由于在!!操作员,从而使在生产中发生故障时更容易查找原因

即使Java确实在后续表达式中抛出了一个NPE,它可能会抛出,也可能不会抛出,这取决于您如何使用应用该表达式的值!!,这将是一个通用的NPE,而不是Kotlin特定的NPE。此外,stacktrace中的行号可能与!!使用,使问题更难理解。

的语义!!表达式表示它在!!运算符,并抛出特定类型的异常KotlinNullPointerException,如果要检查的表达式为null,则该异常是标准NullPointerException的子类。抛出一个特定的异常子类表明异常是由于在!!操作员,从而使在生产中发生故障时更容易查找原因


即使Java确实在后续表达式中抛出了一个NPE,它可能会抛出,也可能不会抛出,这取决于您如何使用应用该表达式的值!!,这将是一个通用的NPE,而不是Kotlin特定的NPE。此外,stacktrace中的行号可能与!!已使用,使问题更难理解。

谢谢。我现在明白了为什么会生成空检查。但是,当空检查与同一行中的方法调用耦合时,是否可以优化空检查,如上例所示。否,因为方法调用不会引发KotlinNullPointerException。谢谢。我现在明白了为什么会生成空检查。但是,当空检查与同一行中的方法调用耦合时,是否可以优化空检查,如上例所示。否,因为方法调用不会引发KotlinNullPointerException。