Kotlin 项目中使用的遗留 Java 库中的空安全 [英] Null safety in legacy Java libraries used in Kotlin projects

查看:24
本文介绍了Kotlin 项目中使用的遗留 Java 库中的空安全的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

Let's say I have particular code in old/legacy Java library:

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) 没有正确注释.

The first two parameters are properly annotated with @NotNull and @Nullable annotations (using jetbrains.annotations). The third one (unnanotatedString) is left without proper annotation.

当我在 Kotlin 代码中使用这个类并将所有构造函数参数设置为非空值时,一切都很好:

When I use this class in my Kotlin code and set all the constructor arguments to non-null values, everything is fine:

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) 上,我可以在没有安全调用的情况下使用它,它编译得很好.

The first value is non-null so I can access it without a safe call. Second value and I need to use safe call (nullableString?.length), if not, I have a compile-time error, so far so good. On the third value (unannotatedString) I can use it without a safe call, it compiles fine.

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

But when I set the third parameter to "null" I don't get a compile-time error (no safe call required, only runtime NullPointerException:

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

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

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

Is that expected behaviour? Is Kotlin's compiler treating not annotated Java methods same as the ones annotated with @NotNull?

推荐答案

从 Kotlin 的角度来看,该变量的类型将是 String!,这是一个 平台类型.

The type of that variable from Kotlin's view will be String!, which is a platform type.

他们最初将来自 Java 的每个变量都设为可空,但后来在语言设计期间改变了这一决定,因为它需要太多的 null 处理,并且需要太多的安全调用使代码变得混乱.

They initially made every variable coming from Java nullable, but they changed that decision later during the design of the language, because it required too much null handling and required too many safe calls that cluttered the code.

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

Instead, it's up to you to assess whether an object coming from Java might be null, and mark their type accordingly. The compiler doesn't enforce null safety for these objects.

再举一个例子,如果您要覆盖 Java 中的方法,参数将再次成为平台类型,您是否将它们标记为可空取决于您.如果你有这个 Java 接口:

As an additional example, if you're overriding a method from Java, the parameters will be platform types yet again, and it's up to you whether you mark them nullable or not. If you have this Java interface:

interface Foo {
    void bar(Bar bar);
}

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

Then these are both valid implementations of it in Kotlin:

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

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

这篇关于Kotlin 项目中使用的遗留 Java 库中的空安全的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆