Retour CompletableFuture ou CompletableFuture?

je veux écrire une méthode asynchrone qui renvoie un CompletableFuture. Le seul but de l'avenir est de suivre quand la méthode est complète, pas son résultat. Serait-il préférable de retour CompletableFuture<Void> ou CompletableFuture<?>? Est-il une raison de préférer l'un ou l'autre, ou sont-ils interchangeables?

notez que je ne demande que les types de retour, pas les listes de paramètres, les déclarations de variables, ou d'autres contextes.

32
demandé sur John Kugelman 2015-12-12 01:10:47

4 réponses

serait-il préférable de retourner CompletableFuture ou CompletableFuture

Est-il une raison de préférer l'un ou l'autre, ou sont-ils sont-ils interchangeables?

il y a trois contextes que le code peut affecter:

  • à l'Exécution, les médicaments génériques ont aucune incidence sur elle.
  • compiler-Je ne peux pas imaginer un cas où une méthode acceptera Future<Void> mais n'accepte pas Future<?>.
  • Développement - si

Future<Void> est préférable.

15
répondu user3707125 2015-12-11 22:46:00

Il est préférable d'utiliser CompletableFuture<Void>.

selon cette réponse trouvé par Sotirios Delimanolis,Future<?> est un défaut mineur de L'API. En Java 6 le submit() méthode Future<Object> interne, et donc son type de retour a été défini à Future<?>. En Java 7, l'implémentation a changé pour utiliser Future<Void> en interne, mais il était trop tard pour changer L'API donc la valeur de retour est restée comme Future<?>.

utilisation des API Java plus récentes Future<Void> et CompletableFuture<Void>. Ceux sont les les exemples que nous devons suivre.

11
répondu John Kugelman 2017-05-23 12:09:05

Regarder CompletableFuture API, vous trouverez que CompletableFuture<Void> est utilisé avec des effets secondaires genre de méthodes où le résultat ne peut être obtenu (car il n'existe pas), ex:

CompletableFuture.runAsync(Runnable runnable);

retour CompletableFuture<Object> ici ce serait déroutant car il n'y a pas de résultat vraiment, nous nous soucions seulement de l'achèvement. Méthodes qui prennent Consumers et Runnables retour CompletableFuture<Void>, ex:thenAccept,thenAcceptAsync. Consumer et Runnable sont utilisées pour les effets secondaires en général.

un Autre cas d'utilisation Void est quand vous ne savez vraiment pas le résultat. Par exemple: CompletableFuture.allOf, la liste passée pourrait être Unfuture Completeputable provenant d'un Runnable, donc nous ne pouvons pas obtenir le résultat.

Ayant dit tout cela, CompletableFuture<Void> est seulement bon si vous n'avez pas d'autre option, si vous pouvez retourner le résultat alors s'il vous plaît allez-y, l'appelant pourrait choisir de jeter s'ils ne sont pas intéressés. Vous avez dit que vous vous intéressez seulement à la fin, alors oui, CompletableFuture<Void> ferait le travail, mais vos utilisateurs D'API vous détesteraient s'ils savaient que CompletableFuture<T> était une option et vous venez de décider en leur nom qu'ils n'auront jamais besoin du résultat.

8
répondu Sleiman Jneidi 2015-12-12 01:44:07

Le type approprié dépend de sa sémantique. Toutes les options énumérées promettent l'achèvement du signal et peuvent retourner asynchrones les exceptions.

  • CompletableFuture<Void>:Void indique à l'utilisateur il n'y a pas de résultat attendu.
  • CompletableFuture<?>? signifie que le type de la valeur contains n'est pas défini dans le sens où n'importe quelle valeur pourrait être livrée.

CompletableFuture classe hérite de plusieurs méthodes pratiques de CompletionStage. Mais il ne permettez à l'appelant de votre méthode de déclencher l'achèvement du futur qui semble erroné parce que votre méthode est responsable de signaler son achèvement lui-même. Il y a aussi un cancel(...) méthode qui est assez inutile dans l'implémentation par défaut de CompletableFuture comme il n'annule pas l'exécution.

  • Future<Void>:Void indique à l'utilisateur il n'y a pas de résultat attendu.
  • Future<?>? signifie que le type de la valeur contains n'est pas défini dans le sens que n'importe quelle valeur pourrait être livré.

Future n'a pas les méthodes de commodité de CompletionStage. Elle ne permet pas de déclencher l'achèvement de l'avenir, mais l'exécution ne peut être annulée.

la prochaine option est CompletionStage<Void>:

  • CompletionStage<Void>:Void indique à l'utilisateur il n'y a pas de résultat attendu. Les méthodes de convenance pour lier les handlers sont présentes mais les cancel(...) la méthode n'est pas. L'appelant de votre méthode ne peut pas déclencher l'achèvement de CompletionStage.
  • <CancellableFuture extends Future<Void> & CompletionStage<Void>>: Ensemble de méthodes d' Future<Void> et CompletionStage<Void>. Il indique qu'il n'y a pas de résultat, des méthodes de commodité sont présents ainsi que l'option d'annuler. L'appelant de votre méthode ne peut pas déclencher l'achèvement d'un CompletionStage.

l'absence de cancel(...) la méthode pourrait correspondre à votre scénario ou non. Par conséquent, je suggère d'aller avec CompletionStage<Void> si vous n'avez pas besoin d'annulation et d'utiliser <CancellableFuture extends Future<Void> & CompletionStage<Void>> si vous avez besoin de l'option d'annuler l'exécution. Si vous choisi <CancellableFuture extends Future<Void> & CompletionStage<Void>> vous voulez probablement créer vous-même une interface qui hérite de Future<Void> et CompletionStage<Void> à utiliser comme type de retour au lieu de mettre l'intersection de type long directement dans votre déclaration de méthode.

vous devriez éviter de revenir avec un type de retour déclaré CompletableFuture en raison de la possibilité pour l'appelant pour déclencher l'achèvement de l'avenir. Le fait de le faire conduit délibérément à confondre le code et à surprendre les pendaisons parce qu'il n'est pas clair quel code est responsable de déclencheur d'achèvement plus. Utilisez l'un des types plus restreints mentionnés pour permettre au système de type d'empêcher l'achèvement involontaire déclenchement par l'appelant de votre méthode.

4
répondu Augustus Kling 2016-11-26 00:50:05