Java 在什么情况下,尽管lambda的返回类型不同,`thenApply()`vs.`thenCompose()`是不明确的?

Java 在什么情况下,尽管lambda的返回类型不同,`thenApply()`vs.`thenCompose()`是不明确的?,java,lambda,language-design,completable-future,Java,Lambda,Language Design,Completable Future,我正在学习完全的未来 我不是在问你。相反,我想问一个感觉不正确的代码气味,以及什么可能真正证明它是正确的 从目前为止我所看到的CompletableFutures的用法来看,似乎你永远不会有这样的情况: CompletableFuture<String> foo = getSomething().thenApply((result) -> { ... }); 若要返回未来,必须使用“撰写”,否则必须使用“应用” 但从经验来看,似乎很奇怪,语言并没有设计出一种方法来消除每次做出

我正在学习完全的未来

我不是在问你。相反,我想问一个感觉不正确的代码气味,以及什么可能真正证明它是正确的

从目前为止我所看到的CompletableFutures的用法来看,似乎你永远不会有这样的情况:

CompletableFuture<String> foo = getSomething().thenApply((result) -> { ... });
若要返回未来,必须使用“撰写”,否则必须使用“应用”

但从经验来看,似乎很奇怪,语言并没有设计出一种方法来消除每次做出这种明确选择的可能性。例如,难道没有一个方法thenDo的返回类型是在编译时从lambda中的返回推断出来的吗?然后在编译时也可以给它类似于apply或compose的属性

但是我相信有一个很好的理由可以使用不同的方法,所以我想知道为什么

这是因为在Java中从lambdas推断返回类型是危险的还是不可能的?我也是Java新手

是否因为有一种情况下,单个方法确实是不明确的,唯一的解决办法是使用单独的方法?我想可能是嵌套的CompletableFutures或复杂的接口和泛型。如果是,有人能提供一个明确的例子吗

是出于其他原因还是有文件证明的建议


供参考,两种方法的签名为:

<U> CompletableFuture<U>   thenApply(Function<? super T,? extends U> fn)
<U> CompletableFuture<U> thenCompose(Function<? super T,? extends CompletionStage<U>> fn)
虽然这是合法的,但使用它确实很痛苦,因为编译器无法检查fn的返回类型是否正确,并且必须接受任何内容

此外,thenDo的实现将没有其他选项,只能应用函数并检查返回的对象是否实现CompletionStage,这除了速度慢和。。。令人厌恶的不雅在非直截了当的情况下会有真正的问题:在一个完整的未来调用thenDo时会发生什么

如果您是java泛型新手,我的建议是首先重点了解两件事:

类型参数的协方差/反方差,或者更确切地说,缺少类型参数。为什么列表不是列表的子类型?列表和列表有什么区别? 类型擦除。为什么不能重载基于泛型参数的方法? 设置好这些变量后,研究如何通过反射解析类型变量,例如:了解Guava的工作原理


编辑:固定了一个链接

供参考,两种方法的签名为:

<U> CompletableFuture<U>   thenApply(Function<? super T,? extends U> fn)
<U> CompletableFuture<U> thenCompose(Function<? super T,? extends CompletionStage<U>> fn)
虽然这是合法的,但使用它确实很痛苦,因为编译器无法检查fn的返回类型是否正确,并且必须接受任何内容

此外,thenDo的实现将没有其他选项,只能应用函数并检查返回的对象是否实现CompletionStage,这除了速度慢和。。。令人厌恶的不雅在非直截了当的情况下会有真正的问题:在一个完整的未来调用thenDo时会发生什么

如果您是java泛型新手,我的建议是首先重点了解两件事:

类型参数的协方差/反方差,或者更确切地说,缺少类型参数。为什么列表不是列表的子类型?列表和列表有什么区别? 类型擦除。为什么不能重载基于泛型参数的方法? 设置好这些变量后,研究如何通过反射解析类型变量,例如:了解Guava的工作原理


编辑:修复了一个链接

您对差异的理解是错误的。然后应用,然后编写返回CompletableFuture的,或者,好的,是CompletionStages

它们之间的区别在于您在结果->{…}部分中隐藏了什么

对于thenApply,您希望该函数返回一个字符串,使整行返回一个completablefuture


对于Compose,您希望该函数返回一个CompleteableFuture,以使整行返回一个CompleteableFuture。

您对差异的理解是错误的。然后应用,然后编写返回CompletableFuture的,或者,好的,是CompletionStages

它们之间的区别在于您在结果->{…}部分中隐藏了什么

对于thenApply,您希望该函数返回一个字符串,使整行返回一个completablefuture


对于thencose,您希望该函数返回一个completablefuture,使整行返回一个completablefuture。

当这些方法不同时,thenDo如何替换它们呢?在你的命名中,他们将是thenDoNow vs.Thendonbackground。它们不一样。这是因为在Java中从lambdas推断返回类型是危险的还是不可能的我不会说这是区分这两种方法的原因,但是是的,这是一个正确的说法。lambda的类型(包括类型参数)是从上下文推断出来的,而不是从上下文推断出来的。@Andreas-我想编译器应该已经知道是否现在就知道了
或者根据lambda中返回的内容来确定背景…@AndrewCheong关于返回的内容?你的意思是说传递什么?是你告诉这个方法你想要它做什么的。@Andreas-看来我完全误解了这些方法。谢谢让我回到最基本的。。。投票决定自动关闭。当这些方法不同的时候,他们怎么能取代这些方法呢?在你的命名中,他们将是thenDoNow vs.Thendonbackground。它们不一样。这是因为在Java中从lambdas推断返回类型是危险的还是不可能的我不会说这是区分这两种方法的原因,但是是的,这是一个正确的说法。lambda的类型(包括类型参数)是从上下文推断出来的,而不是从上下文推断出来的。@Andreas-我想编译器应该已经知道根据lambda中返回的内容是现在还是将来…@AndrewCheong关于返回的内容?你的意思是说传递什么?是你告诉这个方法你想要它做什么的。@Andreas-看来我完全误解了这些方法。谢谢让我回到最基本的。。。投票自动关闭。
<U> CompletableFuture<U> thenDo(Function<? super T,?> fn)