Java 8“可选”不好的做法?

Pet*_*der 2 android kotlin option-type rx-java2

我有一个代码:

val d = Single
            .zip<List<X>, Optional<Y>, DataContent>(
                    xSingle,
                    YSingle,
                    BiFunction { x, y ->
                        val b = if (y.isPresent()) {
                            y.get()
                        } else {
                            null
                        }
                        return@BiFunction DataContent(x, b)
                    })
            .subscribe({ data ->
                ...
            }, { t ->
                ...
            })
Run Code Online (Sandbox Code Playgroud)

我听说,使用Optional检查示例中所示的空值是不好的做法。真的吗?为什么?有人可以展示使用的替代方案RxJava2吗?

Dav*_*son 5

一般来说,Optional它的用例有限,并且有被过度使用的危险。你可以参考Java作者Brian Goetz的这个回答来理解这些(重点是加的):

但我们在添加这个 [java.util.Optional] 功能时确实有一个明确的意图,并且它不是通用的 Maybe 或 Some 类型,尽管很多人都希望我们这样做。我们的目的是为库方法返回类型提供一种有限的机制,其中需要有一种明确的方式来表示“无结果”,而使用 null 则极有可能导致错误。

例如,您可能永远不应该将它用于返回结果数组或结果列表的内容;相反,返回一个空数组或列表。您几乎不应该将其用作某物的字段或方法参数。

在发布的原始示例中,Optional<Y>被用作方法参数,因此这违背了 Java 最佳实践。此外,Maybe这是 RxJava 中的惯用语。

假设您有类似以下内容:

class X
class Y
data class DataContent constructor(val listOfX: List<X>, val y: Y)
Run Code Online (Sandbox Code Playgroud)

您可以编写一个看起来适合您的用例的函数:

fun zipToDataContent(maybeListOfX: Maybe<List<X>>, maybeY: Maybe<Y>): Maybe<DataContent> =
        Maybe.zip<List<X>, Y, DataContent>(
                maybeListOfX,
                maybeY,
                BiFunction { listOfX, y -> DataContent(listOfX, y) })
Run Code Online (Sandbox Code Playgroud)

测试:

@Test
fun testZipToDataContentWithRealY() {
    val x = X()
    val y = Y()

    val maybeListOfX = Maybe.just(listOf(x))
    val maybeY = Maybe.just(y)

    zipToDataContent(maybeListOfX, maybeY).test()
            .assertOf {
                Maybe.just(DataContent(listOf(x), y))
            }
}

@Test
fun testZipToDataContentWithEmptyY() {
    val x = X()

    val maybeListOfX = Maybe.just(listOf(x))
    val maybeY = Maybe.empty<Y>()

    zipToDataContent(maybeListOfX, maybeY).test()
            .assertOf {
                Maybe.empty<DataContent>()
            }
}
Run Code Online (Sandbox Code Playgroud)