Sorry for the poor title, if someone has a better idea I'm open to suggestion.
I was playing around with the CompletableFuture and I stumbled upon something strange.
Let's say you have 2 classes: A and B where B extends A, so B is a subtype of A.
Now, let's declare a CompletableFuture:
CompletableFuture<A> promiseofA = CompletableFuture.supplyAsync(() -> new B());
This is working because B being a subtype of A it conforms to the declaration of the CompletableFuture. Now, if I want to add a exceptionally step, then I have a compiling exception:
CompletableFuture<A> promiseOfA = CompletableFuture.supplyAsync(() -> new B())
.exceptionally(ex -> new B());
In this case Java is complaining, stating that:
Compilation error[ java.util.concurrent.CompletableFuture<B> cannot be converted to java.util.concurrent.CompletableFuture<A>]
Why is it working without the excepionally step and not with it?
It does not work when you add
exceptionallybecause it is completely dependant on the source future for its typing.This means that for exceptionally it sees that the source future is
CompletableFuture<B>, then the type it returns MUST beCompletableFuture<B>.If you specify that the source is actually
CompletableFuture<A>(CompletableFuture.<A>supplyAsync(...)) then it will correctly compile again. It is a problem with the generic type deduction in Java.