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
exceptionally
because 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.