2016-12-14 3 views
2

Désolé pour le titre pauvre, si quelqu'un a une meilleure idée je suis ouvert à la suggestion. Je jouais avec le CompletableFuture et je suis tombé sur quelque chose d'étrange.Java 8 CompletableFuture renvoyant un sous-type de la déclaration

Disons que vous avez 2 classes: A et BB extends A, donc B est un sous-type de A.

Maintenant, Déclarons un CompletableFuture:

CompletableFuture<A> promiseofA = CompletableFuture.supplyAsync(() -> new B()); 

Cela fonctionne parce B étant un sous-type de A est conforme à la déclaration du CompletableFuture. Maintenant, si je veux ajouter une étape exceptionally, j'ai une compilation exception:

CompletableFuture<A> promiseOfA = CompletableFuture.supplyAsync(() -> new B()) 
                .exceptionally(ex -> new B()); 

Dans ce cas, Java se plaint, déclarant que:

Compilation error[ java.util.concurrent.CompletableFuture<B> cannot be converted to java.util.concurrent.CompletableFuture<A>] 

Pourquoi est-il fonctionne sans l'étape excepionally et pas avec ça?

Répondre

6

Cela ne fonctionne pas lorsque vous ajoutez exceptionally car cela dépend complètement de l'avenir de la source pour sa saisie.

Cela signifie qu'exceptionnellement, il voit que le futur source est CompletableFuture<B>, alors le type qu'il renvoie DOIT être CompletableFuture<B>.

Si vous spécifiez que la source est réellement CompletableFuture<A> (CompletableFuture.<A>supplyAsync(...)), elle sera recompilée correctement. C'est un problème avec la déduction de type générique en Java.

+2

spécifiquement: il est l'inférence du type de fonction fournisseur, vous pouvez aussi faire '... supplyAsync ((Fournisseur )() -> new B() ... 'ou juste' ... supplyAsync (() -> (A) nouveau B() ... ' –

0

I ajouté générique qui s'étend A avec à titre exceptionnel, et l'erreur de compilation a disparu:

CompletableFuture<? extends A> promiseOfA1 = CompletableFuture.supplyAsync(() -> new B()) 
      .exceptionally(ex -> new B()); 
+0

Je ne conseillerais pas d'utiliser' extends'/' super' dans les déclarations 'CompletableFuture' car cela empêcherait d'autres appels, par exemple, vous ne pourrez pas appeler' exceptionnally() 'sur' promiseOfA1' –

+0

Hum, d'après ce que j'ai compris, c'est ce qu'il fait là, en appelant '.exceptionally()' dessus, non? –

+0

@MartinGOYOT Ici il il s l'appelant sur le résultat de 'suppliyAsync()', pas sur 'promiseOfA1' - qui serait empêché par son type statique. –