0%

Kotlin 空安全

Kotlin调Java可能返回为空的函数

Java 中的任何引用都可能是 null,这使得 Kotlin 对来自 Java 的对象要求严格空安全是不现实的。 Java 声明的类型在 Kotlin 中会被特别对待并称为平台类型。

当把一个平台值赋值给一个 Kotlin 变量时,可以选择我们期望的类型(可空或非空类型):

1
2
val nullable: String? = item // 允许,没有问题
val notNull: String = item // 允许,运行时可能失败

如果我们选择非空类型,编译器会在赋值时触发一个断言。这防止 Kotlin 的非空变量保存空值。当我们把平台值传递给期待非空值等的 Kotlin 函数时,也会触发断言。 总的来说,编译器尽力阻止空值通过程序向远传播(尽管鉴于泛型的原因,有时这不可能完全消除)。

如果我们选择非空类型,编译器会在赋值时触发一个断言。这防止 Kotlin 的非空变量保存空值。当我们把平台值传递给期待非空值等的 Kotlin 函数时,也会触发断言。 总的来说,编译器尽力阻止空值通过程序向远传播。

只有在Java层给方法加上@Nullable之后才会提示返回值可空。

空安全实际遇到的问题

一开始有一个Java的旧类,一直没有改动过,但是有需求要有不同的实现,所以需要把类的各个方法抽象为接口,接口类用Kotlin实现,接口的实现类还是原来的Java类,其中有个方法在Kotlin的接口中返回值是非空的String,java实现类中返回值是String,但是没有加@NotNull的注解,也就是可空的。

在实际调用这个方法的时候,当java实现类中返回null,就会报空指针异常。

Nullable注解应该是哪个库哪个包的注解?

具有可空性注解的Java类型并不表示为平台类型,而是表示为实际可空或非空的 Kotlin 类型。编译器支持多种可空性注解,包括:

  • JetBrains (org.jetbrains.annotations 包中的 @Nullable 和 @NotNull)

  • Android(com.android.annotations 和 android.support.annotations)

  • JSR-305(javax.annotation,详见下文)

  • FindBugs(edu.umd.cs.findbugs.annotations)

  • Eclipse(org.eclipse.jdt.annotation)

  • Lombok(lombok.NonNull)。

你可以在 Kotlin 编译器源代码中找到完整的列表。

参考资料