Java 返回 CompletableFuture<Void> 还是 CompletableFuture<?>?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/34233375/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 15:26:58  来源:igfitidea点击:

Return CompletableFuture<Void> or CompletableFuture<?>?

javafuturereturn-typecompletable-future

提问by John Kugelman

I want to write an asynchronous method that returns a CompletableFuture. The only purpose of the future is to track when the method is complete, not its result. Would it be better to return CompletableFuture<Void>or CompletableFuture<?>? Is there a reason to prefer one or the other, or are they interchangeable?

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

Note that I'm only asking about return types, not parameter lists, variable declarations, or other contexts.

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

采纳答案by John Kugelman

It is best to use CompletableFuture<Void>.

最好使用CompletableFuture<Void>.

According to this answerfound by Sotirios Delimanolis, Future<?>is a minor API flaw. In Java 6 the submit()method used a Future<Object>internally, and so its return type was set to Future<?>. In Java 7 the implementation changed to use Future<Void>internally, but it was too late to change the API so the return value stayed as Future<?>.

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

Newer Java APIs use Future<Void>and CompletableFuture<Void>. Those are the examples we should follow.

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

回答by user3707125

Would it be better to return CompletableFuture<Void> or CompletableFuture<?>

Is there a reason to prefer one or the other, or are they interchangeable?

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

是否有理由偏爱其中一个,或者它们可以互换?

There are three contexts which code may affect:

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

  • Runtime - generics have no implication on it.
  • Compile - I can't imagine a case where some method will accept Future<Void>but won't accept Future<?>.
  • Development - if Future's result have no meaning, then it is a good practice to say about that to the users through the declaration.
  • 运行时 - 泛型对此没有任何影响。
  • 编译 - 我无法想象某些方法会接受Future<Void>但不会接受的情况Future<?>
  • 开发 - 如果Future的结果没有意义,那么通过声明向用户说明这是一个很好的做法。

So Future<Void>is more preferable.

所以Future<Void>更可取。

回答by Sleiman Jneidi

Looking at the CompletableFutureAPI you will find that CompletableFuture<Void>is used with side effects kind of methods where the result can't be obtained (because it doesn't exist), ex:

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

CompletableFuture.runAsync(Runnable runnable);

returning a CompletableFuture<Object>here would be confusing because there no result really, we only care about the completion. Methods that take Consumersand Runnablesreturn CompletableFuture<Void>, ex : thenAccept, thenAcceptAsync. Consumerand Runnableare used for side effects in general.

CompletableFuture<Object>这里返回 a 会令人困惑,因为实际上没有结果,我们只关心完成情况。获取ConsumersRunnables返回的方法CompletableFuture<Void>,例如 : thenAccept, thenAcceptAsyncConsumer并且Runnable一般用于副作用。

Another use case for Voidis when you really don't know the result. For example: CompletableFuture.allOf, the passed list might be a CompletableFuture originated from a Runnable, so we can't get the result.

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

Having said all of that, CompletableFuture<Void>is only good if you don't have another option, if you can return the result then please go for it, the caller might choose to discard if they are not interested. You said that you are only interested in the completion, then yes, CompletableFuture<Void>would do the job, but your API users would hate you if they know that CompletableFuture<T>was an option and you just decided on their behalf that they will never need the result.

说了这么多,CompletableFuture<Void>只有在你没有其他选择的情况下才好,如果你能返回结果,那就去吧,如果他们不感兴趣,调用者可能会选择放弃。你说你只对完成感兴趣,然后是的,CompletableFuture<Void>会做这项工作,但如果你的 API 用户知道这CompletableFuture<T>是一个选项,你会恨你,而你只是代表他们决定他们永远不需要结果。

回答by Augustus Kling

The suitable type depends on its semantic. All listed options promise to signal completion and may asynchronously return exceptions.

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

  • CompletableFuture<Void>: The Voidtells the user there is no result to be expected.
  • CompletableFuture<?>The ?means the type of the contains value is undefined in the sense that any value could be delivered.
  • CompletableFuture<Void>:Void告诉用户没有预期的结果。
  • CompletableFuture<?>?意味着包含值的类型在任何值都可以传递的意义上是未定义的。

The CompletableFutureclass inherits several convenience methods from CompletionStage. But it does also allow the caller of your method to trigger completion of the future which seems wrong because your method is responsible to signal its completion itself. There is also a cancel(...)method which is pretty pointless in the default implementation of CompletableFutureas it does not cancel the execution.

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

  • Future<Void>: The Voidtells the user there is no result to be expected.
  • Future<?>The ?means the type of the contains value is undefined in the sense that any value could be delivered.
  • Future<Void>:Void告诉用户没有预期的结果。
  • Future<?>?意味着包含值的类型在任何值都可以传递的意义上是未定义的。

Futurelacks the convenience methods from CompletionStage. It does not allow to trigger completion of the future but the execution can be cancelled.

Future缺少来自CompletionStage. 它不允许触发未来的完成,但可以取消执行。

Next option is CompletionStage<Void>:

下一个选项是CompletionStage<Void>

  • CompletionStage<Void>: The Voidtells the user there is no result to be expected. The convenience methods to bind handlers are present but the cancel(...)method is not. The caller of your method cannot trigger the completion of a CompletionStage.
  • <CancellableFuture extends Future<Void> & CompletionStage<Void>>: Set of methods from Future<Void>and CompletionStage<Void>. It tells that there is no result, convenience methods are present as well as the option to cancel. The caller of your method cannot trigger the completion of a CompletionStage.
  • CompletionStage<Void>:Void告诉用户没有预期的结果。绑定处理程序的便捷方法存在,但该cancel(...)方法不存在。您的方法的调用者无法触发CompletionStage.
  • <CancellableFuture extends Future<Void> & CompletionStage<Void>>:来自Future<Void>和的方法集CompletionStage<Void>。它表明没有结果,存在方便的方法以及取消选项。您的方法的调用者无法触发CompletionStage.

The absence of the cancel(...)method might fit your scenario or not. Therefore I suggest to go with CompletionStage<Void>if you don't need cancellation and use <CancellableFuture extends Future<Void> & CompletionStage<Void>>if you require the option to cancel the execution. If you chose <CancellableFuture extends Future<Void> & CompletionStage<Void>>you probably want to create an interface yourself that inherits from Future<Void>and CompletionStage<Void>to be used as return type instead of putting the long type intersection directly in your method declaration.

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

You should avoid returning with a declared return type CompletableFuturebecause of the possibility for the caller to trigger completion of the future. Doing so deliberately leads to confusing code and surprising hangs because it is not clear which code is responsible to trigger completion anymore. Use one of the mentioned more restricted types to let the type system prevent unintentional completion triggering by the caller of your method.

您应该避免使用声明的返回类型返回,CompletableFuture因为调用者有可能触发未来的完成。故意这样做会导致代码混乱和意外挂起,因为不清楚哪个代码负责触发完成。使用上述更受限制的类型之一,让类型系统防止您的方法调用者无意中触发完成。