Reputation: 739
How come the List in the main method below compiles?
class Breakfast {
}
class Drink extends Breakfast {
}
class Juice extends Drink {
}
class Food extends Breakfast {
}
class Bread extends Food {
}
public static void main(String[] args) {
Object object = new Object();
Drink drink = new Drink();
Juice juice = new Juice();
Bread bread = new Bread();
List<? super Drink> firstList = Arrays.asList(object, drink, juice, bread);
List<?> secondList = Arrays.asList(object, drink, juice, bread);
List<? extends Drink> thirdList = Arrays.asList(drink, juice, bread); //DOESN'T COMPILE
}
Seeing as bread is not a superclass of Drink? What is the rule that allows the compilation of the first and second lists but not the third? And if so then what are the main differences between
<?>
and
<? super Drink>
Thanks!
Upvotes: 0
Views: 68
Reputation: 178243
The Java compiler uses type inference to determine the type parameter for calls to generic methods such as Arrays.asList
. It determines the most specific type that can be derived as a supertype to all arguments.
For the first and second lists, there is an Object
in the list, so Object
is the inferred type parameter. That works for ? super Drink
, because ? super Drink
is a lower bound that Object
satisfies. That also works for ?
, the unbounded wildcard, because ?
will match any inferred type parameter. These will compile as long as you have different names for these two list variables.
For the third list (called fourthList
?), you have a lower bound, ? extends Drink
, meaning that the type inferred must be a subtype of Drink
, either Drink
itself or a subclass. Because Breakfast
is the inferred type, and Breakfast
is not a subtype of Drink
, this is a compiler error. If Bread
were not in the list, then the inferred type would be Drink
and this would compile.
Upvotes: 1
Reputation: 106389
extends
is an upper bound - that means that any instance specified must be no "higher" in the inheritance hierarchy than the specified type.
From your example, ? extends Drink
is the upper bound - so every object must then extend from Drink
to be legally assigned into that list.
super
is a lower bound - that means that any instance specified must be no "lower" in the inheritance hierarchy than the specified type.
From your example, ? super Drink
is the lower bound - so every object must then either be a type of Drink
or a type of its ancestor - in this case, Object
.
?
is a wildcard - you actually don't care what type is in the collection if you're using it (since you can't get that information back). By default, that results in ? extends Object
, and thus the upper bound rules apply (and are satisfied).
Upvotes: 0