java - Kotlin 项目中使用的遗留 Java 库中的空安全

标签 java annotations kotlin kotlin-interop kotlin-null-safety

假设我在旧/遗留 Java 库中有特定代码:

public class JavaClass {
    private String notNullString;
    private String nullableString;
    private String unannotatedString;

    public JavaClass(@NotNull String notNullString,
                     @Nullable String nullableString,
                     String unannotatedString) {

        this.notNullString = notNullString;
        this.nullableString = nullableString;
        this.unannotatedString = unannotatedString;
    }

    @NotNull
    public String getNotNullString() {
        return notNullString;
    }

    @Nullable
    public String getNullableString() {
        return nullableString;
    }

    public String getUnannotatedString() {
        return unannotatedString;
    }
}

前两个参数使用@NotNull 和@Nullable 注释进行了正确注释(使用jetbrains.annotations)。第三个 (unnanotatedString) 没有正确的注释。

当我在 Kotlin 代码中使用此类并将所有构造函数参数设置为非空值时,一切正常:

val foo = JavaClass("first string", "second string", "third string")

println("Value1: ${foo.notNullString.length}")
println("Value2: ${foo.nullableString?.length}")
println("Value3: ${foo.unannotatedString.length}")

第一个值是非空的,所以我可以在没有安全调用的情况下访问它。第二个值,我需要使用安全调用(nullableString?.length),如果不是,我有一个编译时错误,到目前为止一切顺利。关于第三个值 (unannotatedString),我可以在没有安全调用的情况下使用它,它编译得很好。

但是当我将第三个参数设置为“null”时,我没有得到编译时错误(不需要安全调用,只有运行时 NullPointerException:

val bar = JavaClass("first string", "second string", null)

println("Value4: ${bar.unannotatedString.length}") // throws NPE

这是预期的行为吗? Kotlin 的编译器对待未注释的 Java 方法是否与使用 @NotNull 注释的方法相同?

最佳答案

从 Kotlin 的角度来看,该变量的类型将是 String!,即 platform type。 .

他们最初让来自 Java 的每个变量都可以为空,但后来在语言设计过程中改变了这个决定,因为它需要太多的 null 处理,并且需要太多的安全调用,这些都使代码困惑.

相反,由您来评估来自 Java 的对象是否可能为 null,并相应地标记它们的类型。编译器不会为这些对象强制执行 null 安全。


再举一个例子,如果您重写 Java 中的方法,参数将再次成为平台类型,是否将它们标记为可空由您决定。如果你有这个 Java 接口(interface):

interface Foo {
    void bar(Bar bar);
}

那么这些都是它在 Kotlin 中的有效实现:

class A : Foo {
    fun bar(bar: Bar?) { ... }
}

class B : Foo {
    fun bar(bar: Bar) { ... }
}

关于java - Kotlin 项目中使用的遗留 Java 库中的空安全,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44551177/

相关文章:

java - 在 Android 中重复执行后台线程的最佳方法?

java - Java中如何获取证书信息

android - 在Android的AlertDialog中处理Edittext

java - Android CameraX 分析图像流

java - 我的构造函数不工作 谁能帮我解决这个问题?

java - 用散列重建路径?

java - 如何监听特殊类初始化?

java - 通过反射获取java注解信息

java - 为什么不能在 Java 中对所有语句都进行注释?

android - 当新值与上一个值相同时,StateFlow 不会发出