Why does this result in a compile error:
Optional<Optional<Integer>> a = Optional.of(Optional.of(1));
Optional<Optional<? extends Number>> b = a;
whereas the following does not?:
Optional<Optional<Integer>> a = Optional.of(Optional.of(1));
Optional<Optional<? extends Number>> c = a.map(x->x);
Although Optional<Integer>
is a sybtype of Optional<? extends Number>
, Optional<Optional<Integer>>
is not a subtype of Optional<Optional<? extends Number>>
. You would get the same compile error if you tried to assign Optional<Integer>
to Optional<Number>
, even if Integer
extends Number
.
To understand it better, replace the Optional<Integer>
whith X
and Optional<? extends Number>
with Y
. You will get:
Optional<X> a = Optional.of(...);
Optional<Y> b = a;
X
is a subtype of Y
, but Optional<X>
is not a subtype of Optional<Y>
, it's a subtype of Optional<? extends Y>
Turns out that Optional<Optional<Integer>>
is a subtype of Optional<? extends Optional<? extends Number>>
.
Now consider the second case:
Optional<Optional<Integer>> a = Optional.of(Optional.of(1));
Optional<Optional<? extends Number>> c = a.map(x->x);
Here the compiler sees that the result of map
should be Optional<Optional<? extends Number>>
and tries to infer that type in the map
method. So the mapper function
Function<? super T, ? extends U> mapper
becomes
Function<? super Optional<Integer>, ? extends Optional<? extends Number>>
because map
returns Optional<U>
and U
in our case is inferred as Optional<? extends Number>
And map
returns exactly what we need:
Optional<? extends Optional<? extends Number>>
So answering your comment
What new information does the
.map(x -> x)
give?
.map(x -> x)
helps the compiler to infer the right type
Helpful resources:
Wildcards and subtyping
Type Inference
Optional<Optional<Integer>> a = Optional.of(Optional.of(1));
//Here the compiler can't infer that you have an Optional<? extends Number>
Optional<Optional<? extends Number>> b = a;
//This would be the correct syntax
Optional<? extends Optional<? extends Number>> b = a;
//Here the map takes a parameter
//Function<? extends Optional<Integer>, Optional<? extends Number>>
//the return value of map is exactly the type that the variable is expecting
Optional<Optional<? extends Number>> c = a.map(x->x);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With