我想编写一个返回CompletableFuture
的异步方法。未来的唯一目的是追踪方法何时完成,而不是结果。返回test.f90: In function 'test':
test.f90:9:0: warning: 'cosmphi.dim[2].stride' may be used uninitialized in this function [-Wmaybe-uninitialized]
real, dimension(:, :, :), allocatable :: cosMPhi
^
test.f90:9:0: warning: 'cosmphi.dim[1].ubound' may be used uninitialized in this function [-Wmaybe-uninitialized]
test.f90:9:0: warning: 'cosmphi.dim[1].stride' may be used uninitialized in this function [-Wmaybe-uninitialized]
test.f90:9:0: warning: 'cosmphi.dim[0].ubound' may be used uninitialized in this function [-Wmaybe-uninitialized]
test.f90:9:0: warning: 'cosmphi.offset' may be used uninitialized in this function [-Wmaybe-uninitialized]
或CompletableFuture<Void>
会更好吗?有理由偏爱其中一个,还是可以互换?
CompletableFuture
本身会从许多方法中返回CompletableFuture<?>
。CompletableFuture<Void>
在AsynchronousSocketChannel
java.nio
中有一个Future<Void>
。ExecutorService
和ScheduledExecutorService
等Future<Void> connect(SocketAddress remote)
类会返回java.util.concurrent
:例如,使用Future<?>
。请注意,我只询问返回类型,而不是参数列表,变量声明或其他上下文。
答案 0 :(得分:16)
返回CompletableFuture&lt; Void&gt;会更好吗?要么 CompletableFuture&LT;?&GT;
是否有理由偏好其中一个,或者是他们 可互换?
代码可能会影响三种情境:
Future<Void>
但又不接受Future<?>
的情况。Future
的结果没有意义,那么通过声明向用户说明这一点是一个好习惯。因此Future<Void>
更为可取。
答案 1 :(得分:16)
最好使用CompletableFuture<Void>
。
Sotirios Delimanolis,Future<?>
是一个次要的API漏洞。在Java 6中,submit()
方法在内部使用Future<Object>
,因此其返回类型设置为Future<?>
。在Java 7中,实现更改为在内部使用Future<Void>
,但更改API为时已晚,因此返回值保持为Future<?>
。
较新的Java API使用Future<Void>
和CompletableFuture<Void>
。这些是我们应该遵循的例子。
答案 2 :(得分:8)
查看CompletableFuture
API,您会发现CompletableFuture<Void>
与副作用一起用于无法获得结果的方法(因为它不存在),例如:
CompletableFuture.runAsync(Runnable runnable);
在这里返回CompletableFuture<Object>
会让人感到困惑,因为没有真正的结果,我们只关心完成。将Consumers
和Runnables
返回CompletableFuture<Void>
的方法,例如:thenAccept
,thenAcceptAsync
。 Consumer
和Runnable
通常用于副作用。
Void
的另一个用例是当你真的不知道结果时。例如:CompletableFuture.allOf
,传递的列表可能是源自Runnable的CompletableFuture,因此我们无法获得结果。
说完所有这些后,CompletableFuture<Void>
只有在你没有其他选择的情况下才有用,如果你可以返回结果那么请你去,如果他们不是,那么来电者可能会选择丢弃感兴趣。你说你只对完成感兴趣,然后是的,CompletableFuture<Void>
可以胜任这项工作,但是如果他们知道CompletableFuture<T>
是一个选项并且你刚刚代表他们做出选择,那么你的API用户就会讨厌你他们永远不会需要结果。
答案 3 :(得分:4)
合适的类型取决于其语义。所有列出的选项都承诺信号完成,并可能异步返回异常。
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>
的接口以用作返回类型,而不是将long类型交集直接放在方法声明中。< / p>
您应该避免使用声明的返回类型CompletableFuture
返回,因为调用者可能会触发将来的完成。故意这样做会导致令人困惑的代码和令人惊讶的挂起,因为不清楚哪个代码负责触发完成。使用上述更受限制的类型之一让类型系统防止方法调用者触发意外完成。