Kotlin RxJava可空错误
我使用Kotlin和RxJava在我的Android应用程序中遇到了一个问题。 如下所示。
import rx.Observable data class TestUser(val name: String) fun getTestUser(): Observable<TestUser> { return Observable.just(TestUser("Brian")).flatMap { getUser() } // this compiles } fun getTestUser2(): Observable<TestUser> { val observable = Observable.just(TestUser("Brian")).flatMap { getUser() } return observable // this does not compile } fun getUser(): Observable<TestUser?> { return Observable.just(null) }
在getTestUser2
,编译器推断最终的返回类型为Observable<TestUser?>
,并且不能编译。 然而,在getTestUser
,代码会进行编译,并且在运行时,当TestUser
返回null
时,该observable的任何订阅者可能会感到惊讶。
我猜这是在Kotlin和Java之间来回切换的。 但是,编译器可以看到getTestUser2
的差异, getTestUser2
让我觉得这是可以getTestUser2
。
编辑
这是Kotlin 1.0,昨天发布的最终版本(2016年2月15日)。
在Kotlin中使用flatMap
函数的签名如下:
public final fun <R: Any!, T: Any!> Observable<T>.flatMap( func: ((T) -> Observable<out R!>!)! ) : Observable<R!>!
从文档:
Java中的任何引用都可能为
null
,这使得Kotlin对来自Java的对象的严格无效安全的要求是不切实际的。 Java声明的类型在Kotlin中被专门处理,并被称为平台类型。 这种类型的空检查是放松的,所以它们的安全保证和Java一样
和
T!
意思是“T
还是T?
”
这意味着Kotlin编译器可以将flatMap
函数的返回类型视为Observable<TestUser>
或Observable<TestUser?>
,甚至可以将Observable<TestUser>?
。 放松部分说,“我们不想用这些不知名的类型来打扰你,你可能知道得更好”。
由于返回类型是在getTestUser()
明确给出的,因此它使用第一个。 由于observable
的类型没有明确给出,因此它根据getUser()
函数将其推断为Observable<TestUser?>
。
正如@voddan评论的那样,有一个讨论这个问题的公开的问题: https ://youtrack.jetbrains.com/issue/KT-11108