尽管lambda的返回类型,`thenApply()`与`thenCompose()`是不明确的是什么情况?

And*_*ong 1 java lambda language-design completable-future

我正在学习CompletableFutures.

我不是在问之间的区别thenApply()thenCompose().相反,我想问一下感觉不对的代码"气味",以及实际可能证明它的理由.

CompletableFuture我到目前为止看到的用法来看,似乎你从来没有这样:

CompletableFuture<String> foo = getSomething().thenApply((result) -> { ... });
Run Code Online (Sandbox Code Playgroud)

这不是:

String foo = getSomething().thenCompose((result) -> { ... });
Run Code Online (Sandbox Code Playgroud)

要返回未来,您必须使用thenCompose(),否则thenApply().

然而,从经验来看,语言并没有设法消除每次都做出这种明确的选择,这似乎很奇怪.例如,是否有一个单一的方法,thenDo()其返回类型是从returnlambda中推断出来的(在编译期间)?它可能然后被给予thenApplythenCompose在编译时般的性能以及.

但我确信有一个很好的理由采用不同的方法,所以我想知道原因.

  • 是因为在Java中从lambda推断返回类型是危险还是不可能?(我也是Java的新手.)

  • 是不是因为有一种情况,单个方法确实不明确,唯一的解决方案是使用单独的方法?(我想象可能,嵌套CompletableFuture或复杂的界面和泛型.)如果是这样,有人可以提供一个明确的例子吗?

  • 是出于其他原因还是有记录的推荐?

gio*_*iga 5

作为参考,这两种方法的签名是:

<U> CompletableFuture<U>   thenApply(Function<? super T,? extends U> fn)
<U> CompletableFuture<U> thenCompose(Function<? super T,? extends CompletionStage<U>> fn)
Run Code Online (Sandbox Code Playgroud)

Function<? super T,? extends U>并且Function<? super T,? extends CompletionStage<U>>Function<? super T, ?>一个共同的超类型(好吧,技术上它只是Function).

因此签名thenDo将是这样的:

<U> CompletableFuture<U> thenDo(Function<? super T,?> fn)
Run Code Online (Sandbox Code Playgroud)

虽然合法,但由于编译器无法检查返回类型fn是否正确并且必须接受任何内容,因此使用它会非常麻烦.

此外,这个实施thenDo就没有别的选择,只能apply功能,检查是否返回的对象implements CompletionStage,它(除了速度慢和... repugnantly不雅)将在非简单的情况下,真正的问题:什么会打电话时发生thenDo的一个CompletableFuture<CompletionStage<String>>


如果您是java泛型的新手,我的建议是首先集中精力理解两件事:

  1. 类型参数的协方差/逆变(或者更确切地说是缺乏).为什么不是List<String>子类型List<Object>List<Object>和之间有什么区别List<?>
  2. 键入擦除.为什么我不能基于泛型参数重载方法?

设置好后,研究如何通过反射解析类型变量(例如:了解Guava的TypeToken工作原理)


编辑:修复了一个链接