问题 Kotlin RxJava Nullable Bug


我在使用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

我猜这与在Kotlin和Java之间来回走动有关。但是,编译器的事实 能够 看到差异 getTestUser2 让我觉得这可以解决。

编辑

这是在Kotlin 1.0,即昨天(2016年2月15日)发布的最终版本。


2903
2018-02-16 19:21


起源

我想,这是他们使用的问题跟踪器: youtrack.jetbrains.com/issues/KT 。如果您创建错误报告,则更有可能从该语言的创建者那里收到确认/解释 - Balázs Édes
该团队证实这是一个错误。问题: youtrack.jetbrains.com/issue/KT-11108 - voddan


答案:


签名 flatMap 在Kotlin中使用时的功能如下:

public final fun <R: Any!, T: Any!> 
    Observable<T>.flatMap(
      func: ((T) -> Observable<out R!>!)!
    ) : Observable<R!>!

来自文档:

Java中的任何引用都可能是 null这使得Kotlin的要求   对于来自Java的对象,严格的null安全性是不切实际的。类型   Java声明在Kotlin中被特别处理并被调用   平台类型。对这些类型放宽空检,以确保安全   它们的保证与Java相同

T! 意思是“T 要么 T?

这意味着Kotlin编译器可以考虑返回类型 flatMap 作为任何一个 Observable<TestUser> 要么 Observable<TestUser?>, 甚至 Observable<TestUser>?。放松部分说的很多,“我们不想用这些未知的类型打扰你,你可能知道的更好”。

由于返回类型是明确给出的 getTestUser(),它使用第一个。自从类型 observable 是  明确给出,它推断它 Observable<TestUser?>,基于 getUser() 功能。


正如@voddan评论的那样,有一个未解决的问题在讨论这个问题: https://youtrack.jetbrains.com/issue/KT-11108


10
2018-02-16 19:55



接受这个。精心研究和呈现。这就说得通了。我可能会通过在返回之前分配值来开始更明确,就像在第二个例子中一样。我想要所有类型的安全性。 - bclymer
这很奇怪。没有类型声明的赋值不应该改变。 - voddan
该团队证实这是一个错误。问题: youtrack.jetbrains.com/issue/KT-11108 - voddan
@voddan很有意思! - nhaarman