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
Return CompletableFuture<Void> or CompletableFuture<?>?
提问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<?>?是否有理由偏爱其中一个,或者它们可以互换?
CompletableFutureitself returnsCompletableFuture<Void>from many of its methods.java.niohas aFuture<Void>inAsynchronousSocketChannel:Future<Void> connect(SocketAddress remote).- On the other hand,
java.util.concurrentclasses likeExecutorServiceandScheduledExecutorServicereturnFuture<?>: for instance, withFuture<?> submit(Runnable task).
CompletableFuture它本身CompletableFuture<Void>从它的许多方法中返回。java.nio有一个Future<Void>在AsynchronousSocketChannel:Future<Void> connect(SocketAddress remote)。- 另一方面,
java.util.concurrent类喜欢ExecutorService和ScheduledExecutorService返回Future<?>:例如,使用Future<?> submit(Runnable task).
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 acceptFuture<?>. - 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 会令人困惑,因为实际上没有结果,我们只关心完成情况。获取Consumers和Runnables返回的方法CompletableFuture<Void>,例如 : thenAccept, thenAcceptAsync。Consumer并且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>: TheVoidtells 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>: TheVoidtells 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>: TheVoidtells the user there is no result to be expected. The convenience methods to bind handlers are present but thecancel(...)method is not. The caller of your method cannot trigger the completion of aCompletionStage.<CancellableFuture extends Future<Void> & CompletionStage<Void>>: Set of methods fromFuture<Void>andCompletionStage<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 aCompletionStage.
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因为调用者有可能触发未来的完成。故意这样做会导致代码混乱和意外挂起,因为不清楚哪个代码负责触发完成。使用上述更受限制的类型之一,让类型系统防止您的方法调用者无意中触发完成。

