Return CompletableFuture<Void> 或 CompletableFuture<?>?

Return CompletableFuture<Void> or CompletableFuture<?>?

我想编写一个 return 是 CompletableFuture 的异步方法。 future 的唯一目的是跟踪方法何时完成,而不是其结果。 returnCompletableFuture<Void>好还是CompletableFuture<?>好?有理由偏爱其中之一,还是可以互换?

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

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

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

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

  • 运行时 - 泛型对其没有影响。
  • 编译 - 我无法想象某些方法会接受 Future<Void> 但不会接受 Future<?>.
  • 的情况
  • 开发 - 如果 Future 的结果没有意义,那么最好通过声明向用户说明。

所以Future<Void>更可取。

看一下CompletableFuture API你会发现CompletableFuture<Void>是用了一些有副作用的方法,结果得不到(因为它不存在) ), 例如:

CompletableFuture.runAsync(Runnable runnable);

return在这里输入 CompletableFuture<Object> 会令人困惑,因为实际上没有结果,我们只关心完成。采用 ConsumersRunnables return CompletableFuture<Void> 的方法,例如:thenAcceptthenAcceptAsyncConsumerRunnable 通常用于副作用。

Void 的另一个用例是当您真的不知道结果时。例如:CompletableFuture.allOf,传过来的list可能是一个CompletableFuture,来源于一个Runnable,所以我们拿不到结果。

综上所述,CompletableFuture<Void>只有在你没有其他选择的情况下才是好的,如果你能return结果那么请去吧,来电者可能会选择放弃如果他们不感兴趣。你说你只对完成感兴趣,那么是的,CompletableFuture<Void> 可以完成这项工作,但是如果你的 API 用户知道 CompletableFuture<T> 是一个选项而你只是代表他们决定他们永远不需要结果。

最好用CompletableFuture<Void>.

According to this answer found by Sotirios DelimanolisFuture<?> 是一个小 API 缺陷。在 Java 6 中,submit() 方法在内部使用了 Future<Object>,因此它的 return 类型被设置为 Future<?>。在 Java 7 中,实现更改为在内部使用 Future<Void>,但更改 API 为时已晚,因此 return 值保持为 Future<?>

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

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

  • CompletableFuture<Void>Void 告诉用户没有预期的结果。
  • CompletableFuture<?> ? 表示包含值的类型未定义,可以传递任何值。

CompletableFuture class 从 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> 的接口,以用作 return 类型,而不是将 long 类型交集直接放在您的方法声明。

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