我在以下代码中收到一个 RARE 空指针异常:
class Artist {
fun draw(canvas: Canvas, state: State){
state.drawableObjects.forEach {
it.draw(canvas) //NULL POINTER!?! Can not call draw(Canvas) on null object
}
}
}
class State {
var drawableObjects = listOf<DrawableObject>()
set(value) {
field = value.filter { it.isVisible } // Why not crash here if null?
}
}
class DrawableObject(val isVisible: Boolean) {
fun draw(canvas: Canvas) { }
}
Run Code Online (Sandbox Code Playgroud)
这怎么可能?列表 drawableObjects 是不可变的。它也不允许空对象。当列表更改时,会设置一个全新的列表以防止在绘制调用期间进行修改。
我绝对应该提到涉及多个线程。仅 2 个线程。一个调用 Artist.draw() 和第二个调用 State.drawableObjects = listOf()
我不知道你的数据结构,所以让我们举一个更简单的例子。
假设您尝试List<String>在 Kotlin 中填充 a 。String是不可为空的,因此您的 Kotlin 代码将期望 中的所有元素List都不是null。
但是,您可能List<String>来自 Java 代码。在 Java 中,null将List. 而且 Java 代码不一定是你的——它可以来自一个库,比如 Gson。
所以,假设你让 Gson 解析这个 JSON:
[
"the",
"quick",
"brown",
null,
"jumped",
"over",
"the",
"lazy",
null
]
Run Code Online (Sandbox Code Playgroud)
Gson 很乐意将其解析为 Kotlin List<String>,并且 Kotlin 的 JVM 互操作将允许它。但是,当您开始迭代 that 时List<String>,您将NullPointerException因null元素而崩溃。
类似地,Gson 将null在解析缺少某些属性的 JSON 对象时保留 Kotlin属性。假设你有:
data class Something(foo: Int, bar: Int)
Run Code Online (Sandbox Code Playgroud)
和:
{ foo: 42 }
Run Code Online (Sandbox Code Playgroud)
Gson 会很高兴地创建一个设置为的Something实例。barnull
因此,根据您的一条评论,我的猜测是 Gson 正在根据其解析规则为您提供null值List<DrawableObject>。您可以通过将其设置为 aList<DrawableObject?>然后对null元素执行某些操作来解决此问题(过滤掉它们,在forEach循环中跳过它们等)。
| 归档时间: |
|
| 查看次数: |
351 次 |
| 最近记录: |