<? super T> <? super T> inside <T extends Juicy<? super T>> <T extends Juicy<? super T>> exists so that RedOrange , which is a subclass of Juicy<Orange> , can be within it.
First imagine <<20>:
public <T extends Juicy<T>> List<Juice<T>> squeeze(List<T> fruits) {...
Now T should be Juicy<T> . The class Orange is a Juicy<T> , a Juicy<Orange> . But the RedOrange class RedOrange not Juicy<T> . This is not a Juicy<RedOrange> ; this is a Juicy<Orange> . Therefore, when we try to call squeeze :
List<RedOrange> redOranges = new ArrayList<RedOrange>(); List<Juice<RedOrange>> juices = squeeze(redOranges);
we get the following compiler error:
Inferred type 'RedOrange' for type parameter 'T' is not within its bound; should implement 'Juicy<RedOrange>'.
If we put <? super T> <? super T> , which allows the type parameter for Juicy be a superclass of T This allows you to use RedOrange because it is Juicy<Orange> and Orange is a superclass before RedOrange .
public <T extends Juicy<? super T>> List<Juice<T>> squeeze(List<T> fruits) {...
Now the squeeze command call above compiles.
EDIT
But what if we want to squeeze a List<Juice<Orange>> from a List<RedOrange> ? It turned out a little more complicated, but I found a solution:
We need a parameter of the second type to match Orange in the squeeze method:
public <S extends Juicy<S>, T extends Juicy<S>> List<Juice<S>> squeeze(List<T> fruits)
Here S represents Orange , so that we can return List<Juice<Orange>> . Now we can say
List<RedOrange> redOranges = new ArrayList<RedOrange>(); List<Juice<Orange>> juices = squeeze(redOranges);
rgettman
source share