微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

抛出 NoWhenBranchMatchedException 时如何穷举?

如何解决抛出 NoWhenBranchMatchedException 时如何穷举?

我观察到带有详尽 when 语句的 LiveData,它如何在运行时抛出 NowhenBranchMatchedException?编译时没有检查穷举吗?

enum class MyEnum { Foo,Bar }

liveData.observe(viewLifecycleOwner) { enumInstance ->
  val instance: MyEnum = when (enumInstance) {
    is Foo -> {}
    is Bar -> {}
  }
}

解决方法

为什么会发生

因为 LiveData 是一个用 Java 编写的 API,并且在 Java 中任何类型都可以为 null,所以 Kotlin 的 null-safety 不会在编译时强制执行。 IntelliJ IDE 使用 ! 后缀引用这些类型:

T! 表示“TT?”(source

enumInstance 可能是 null,但 Kotlin 不会对其进行任何空检查,因为 Observer 是一个 Java 接口。这就是为什么编译器仍然认为这个 when 语句是详尽无遗的,即使它不是。将示例中的 LiveData 的值设置为 null 将导致在运行时抛出 NoWhenBranchMatchedException

liveData.value = Foo // Perfectly safe at runtime
liveData.value = null // NOT safe at runtime
liveData.observe(viewLifecycleOwner,Observer { enumInstance ->
  // enumInstance is "MyEnum!" (nullability unknown to Kotlin)
  val instance = when (enumInstance) {
    is Foo -> {}
    is Bar -> {}
  }
})

Java 中的任何引用都可能为空,这使得 Kotlin 对来自 Java 的对象的严格空安全要求不切实际。 Java 声明的类型在 Kotlin 中以特定方式处理,称为平台类型。此类类型的空检查放宽,因此它们的安全保证与 Java 中的相同 [...] (source)

你能做些什么来防止它

具有编译时安全性

如果它来自 Java,要么检查 null,要么随时假设它可以为 null。使类型对 Kotlin 显式。

我们在做什么:

val unknownNullability = javaApi.getString() // "String!"
unknownNullability.split(',') // Runtime error

我们应该做什么:

val knownToBeNullable: String? = javaApi.getString()
knownToBeNullable.split(',') // Compile-time error

修复示例代码:

liveData.observe(viewLifecycleOwner,Observer { enumInstance: MyEnum? ->
  // Now I know I may receive null
  // This will fail at compile-time:
  when (enumInstance) {
    is Foo -> {}
    is Bar -> {}
    // null case is required now
  }
})

没有编译时安全

您可以简单地避免将 nullLiveData 一起使用(以及其他具有 Java 互操作性的地方)。除非您发布,否则观察者不会收到 null。

liveData.value = Foo
liveData.observe(viewLifecycleOwner,Observer { enumInstance ->
  // I'm sure I won't receive null
})

然而,代码不断变化。即使您今天的代码从未发布 null,但有一天它可能会发布,并且使用这种方法,任何可空性错误只会在运行时出现。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?