我有Dao
来返回简单对象。如果对象不存在,房间返回null
,但安卓应用程序不会崩溃。另外,如果我将该值赋值给非空变量,则应用程序中不会出现崩溃。
Dao:
@Query("SELECT * FROM users WHERE id LIKE :id LIMIT 1")
abstract fun getById(id: Long): User
不是崩溃代码:
doAsync {
val user: User = userDao.getById(999) // user 999 not exist, userDao returns null
uiThread {
if (user == null) {
Timber.d("user is $user") // "user is null" in log
} else {
Timber.d("user is ${user.email}")
}
}
}
我有两个问题:
发布于 2018-11-07 11:56:57
这都是关于Kotlin如何用Java代码处理边界上的空值。
如果将null从Java传递给需要非空值的Kotlin方法,则会得到异常。这是通过Kotlin编译器在方法开头添加对Intrinsics.checkNotNull
函数的调用来实现的。
例如:
fun hello(who: String): Unit {
println ("Hello $who")
}
变成了
public final void hello(@NotNull String who) {
Intrinsics.checkParameterIsNotNull(who, "who");
String var2 = "Hello " + who;
System.out.println(var2);
}
在从Kotlin调用Java方法时添加了类似的检查。
但是在您的例子中,您有Kotlin接口,它是由Room生成的Java实现的。因此Kotlin编译器不能添加检查,因为它无法控制所有接口实现。否则,它将不得不在每次调用Kotlin类或接口之后添加检查,因为它可以在Java中实现,这不利于性能。
UPD:在Room bugtracker https://issuetracker.google.com/issues/112323132发现了类似的问题。Googler表示,这是有意的行为,如果您编写了可以返回空值的查询,那么您就有责任在dao接口中将其标记为可空。
发布于 2018-11-07 11:47:20
您没有得到NullPointerException
的原因很简单: Room是一个Java,而不是Kotlin,所以它不知道您的User
不应该是null。在与Java代码进行接口时,Kotlin引入了一些空检查来给出异常,但是由于您的接口是用Kotlin编写的,所以它假定这不会有问题,因此跳过检查。
我不是一个房间专家,但在谷歌搜索之后,我找不到一种方法来强迫Room检查空值。我看到了解决你的“问题”的两种方法:
getById
函数以返回User?
@Dao
转换为Java接口,迫使Kotlin检查null。发布于 2018-11-07 11:20:11
正如我所理解的,您生成的Dao类没有在Java代码中将返回值注释为@Nullable。
@Override
public User getById(long id) {
应该是
@Override
public @Nullable User getById(long id) {
因此,您没有看到警告
https://stackoverflow.com/questions/53186937
复制相似问题