下面的主要方法中的列表如何编译?
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
}
看到面包不是饮料的超类?允许编译第一和第二列表而不是第三列表的规则是什么?如果是这样,
之间的主要区别是什么<?>
和
<? super Drink>
谢谢!
答案 0 :(得分:1)
Java编译器使用类型推断来确定用于调用诸如Arrays.asList
之类的通用方法的类型参数。它确定可以作为所有参数的超类型派生的最特定类型。
对于第一和第二个列表,列表中有一个Object
,因此Object
是推断的类型参数。这适用于? super Drink
,因为? super Drink
是Object
满足的下限。这也适用于?
(无界通配符),因为?
将匹配任何推断的类型参数。只要您为这两个列表变量使用不同的名称,它们就会编译。
对于第三个列表(称为fourthList
?),您有一个下界? extends Drink
,这意味着推断的类型必须是Drink
的子类型,即{{1} }本身或子类。因为Drink
是推断的类型,并且Breakfast
不是Breakfast
的子类型,所以这是编译器错误。如果Drink
不在列表中,则推断的类型将为Bread
并将编译。
答案 1 :(得分:0)
extends
是上限的边界-这意味着在继承层次结构中,指定的任何实例都不得比指定的类型“更高”。
在您的示例中,? extends Drink
是上限-因此每个对象都必须从Drink
延伸,才能合法地分配到该列表中。
super
是 lower 的下界-意味着在继承层次结构中,指定的任何实例都不得比指定的类型“低”。
在您的示例中,? super Drink
是下界-因此每个对象都必须是Drink
的类型或其祖先的类型-在这种情况下为Object
。 / p>
?
是通配符-如果您使用的是集合,实际上您根本不会在意它们是什么类型(因为您无法获取该信息)。默认情况下,结果为? extends Object
,因此上限规则适用(并得到满足)。