A type-bound nested generic expression results in a compilation error

Why does this lead to a compilation error:

Optional<Optional<Integer>> a = Optional.of(Optional.of(1)); Optional<Optional<? extends Number>> b = a; 

whereas the following:

 Optional<Optional<Integer>> a = Optional.of(Optional.of(1)); Optional<Optional<? extends Number>> c = a.map(x->x); 
+7
java generics
source share
2 answers

Although Optional<Integer> is sybtype Optional<? extends Number> Optional<? extends Number> , Optional<Optional<Integer>> not a subtype of Optional<Optional<? extends Number>> Optional<Optional<? extends Number>> . You would get the same compilation error if you tried to assign Optional<Integer> to Optional<Number> , even if Integer extends Number .

To understand this better, replace Optional<Integer> whith X and Optional<? extends Number> Optional<? extends Number> to Y You'll get:

 Optional<X> a = Optional.of(...); Optional<Y> b = a; 

X is a subtype of Y , but Optional<X> not a subtype of Optional<Y> , it is a subtype of Optional<? extends Y> Optional<? extends Y>

It turns out that Optional<Optional<Integer>> is a subtype of Optional<? extends Optional<? extends Number>> Optional<? extends Optional<? extends Number>> 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 map result should be Optional<Optional<? extends Number>> Optional<Optional<? extends Number>> and tries to infer this type in the map method. So the display 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 displayed as Optional<? extends Number> Optional<? extends Number>

And map returns exactly what we need:

 Optional<? extends Optional<? extends Number>> 

So, in response to your comment

What new information .map(x -> x) provide?

.map(x -> x) helps the compiler infer the correct type

Useful resources:

+2
source share
 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); 
+1
source share

All Articles