返回CompletableFuture <Void>或CompletableFuture <?>?

Joh*_*ica 46 java future return-type completable-future

我想写一个返回a的异步方法CompletableFuture.未来的唯一目的是跟踪方法何时完成,而不是结果.返回CompletableFuture<Void>还是更好CompletableFuture<?>?有理由偏爱其中一个,还是可以互换?

请注意,我只询问返回类型,而不是参数列表,变量声明或其他上下文.

Joh*_*ica 20

最好用CompletableFuture<Void>.

根据Sotirios Delimanolis发现的这个答案,Future<?>是一个小的API漏洞.在Java 6中,该submit()方法在Future<Object>内部使用,因此其返回类型设置为Future<?>.在Java 7中,实现更改为在Future<Void>内部使用,但更改API为时已晚,因此返回值保持不变Future<?>.

较新的Java API使用Future<Void>CompletableFuture<Void>.这些是我们应该遵循的例子.


use*_*125 18

返回CompletableFuture <Void>或CompletableFuture <?>会更好吗?

有理由偏爱其中一个,还是可以互换?

代码可能会影响三种上下文:

  • 运行时 - 泛型对它没有任何影响.
  • 编译 - 我无法想象某种方法会接受Future<Void>但不接受的情况Future<?>.
  • 开发 - 如果Future结果没有意义,那么通过声明向用户说明这一点是一个好习惯.

所以Future<Void>更可取.


Sle*_*idi 10

查看CompletableFutureAPI,你会发现它CompletableFuture<Void>与副作用一起用于无法获得结果的方法(因为它不存在),例如:

CompletableFuture.runAsync(Runnable runnable);
Run Code Online (Sandbox Code Playgroud)

返回 CompletableFuture<Object>这里会让人感到困惑,因为没有真正的结果,我们只关心完成.称取方法ConsumersRunnables返回CompletableFuture<Void>,例如:thenAccept,thenAcceptAsync.Consumer并且Runnable通常用于副作用.

另一个用例Void是当你真的不知道结果时.例如:CompletableFuture.allOf,传递的列表可能是源自Runnable的CompletableFuture,因此我们无法获得结果.

说完所有这些,CompletableFuture<Void>只有你没有其他选择才有用,如果你可以返回结果然后请去,如果他们不感兴趣,调用者可能会选择丢弃.你说你只对完成感兴趣,然后是的,CompletableFuture<Void>会做这个工作,但如果他们知道这CompletableFuture<T>是一个选项而你的API用户会讨厌你,你只是代表他们决定他们永远不需要结果.


Aug*_*ing 5

合适的类型取决于其语义。所有列出的选项均承诺完成信号,并可能异步返回异常。

  • CompletableFuture<Void>Void告诉用户没有预期的结果。
  • CompletableFuture<?>?装置包含值的类型在这个意义上,任何值可以交付不确定的。

CompletableFuture类继承几个方便的方法CompletionStage。但是它也允许您的方法的调用者触发将来的完成,这似乎是错误的,因为您的方法负责自己完成的信号。还有一种cancel(...)方法在默认实现中毫无意义,CompletableFuture因为它不会取消执行。

  • Future<Void>Void告诉用户没有预期的结果。
  • Future<?>?装置包含值的类型在这个意义上,任何值可以交付不确定的。

Future缺乏的便捷方法CompletionStage。它不允许触发将来的完成,但可以取消执行。

下一个选项是CompletionStage<Void>

  • CompletionStage<Void>Void告诉用户没有预期的结果。存在绑定处理程序的便捷方法,但cancel(...)没有。方法的调用者无法触发的完成CompletionStage
  • <CancellableFuture extends Future<Void> & CompletionStage<Void>>:设置从方法Future<Void>CompletionStage<Void>。它表明没有结果,提供了便捷方法以及取消选项。方法的调用者无法触发的完成CompletionStage

缺少该cancel(...)方法可能适合您的情况。因此,我建议CompletionStage<Void>您在不需要取消的情况下使用<CancellableFuture extends Future<Void> & CompletionStage<Void>>,并在需要取消执行的选项时使用。如果选择<CancellableFuture extends Future<Void> & CompletionStage<Void>>,则可能要自己创建一个继承Future<Void>CompletionStage<Void>用作返回类型的接口,而不是将长类型交集直接放在方法声明中。

您应该避免使用声明的返回类型返回,CompletableFuture因为调用者有可能触发将来的完成。这样做有意导致代码混乱,并且挂起令人惊讶的挂起,因为尚不清楚哪个代码负责触发完成。使用上述更受限制的类型之一,以使类型系统防止方法的调用者意外完成触发。