一个例子来自布鲁斯·艾克尔的书“解说中的问题”。
class GenericWriting{
static <T> void writeExact(List<T> list, T item) {
list.add(item);
}
static List<Apple> apples = new ArrayList<Apple>();
static List<Fruit> fruits = new ArrayList<Fruit>();
static void f1() {
writeExact(apples, new Apple());
writeExact(fruits, new Apple()); /* why the compiler does not produce an error because the invariance of types is violated */
}
static <T> void writeWithWildcard(List<? super T> list, T item) {
list.add(item);
}
static void f2() {
writeWithWildcard(apples, new Apple());
writeWithWildcard(fruits, new Apple());
}
public static void main(String[] args) {
f1();
f2();
}
}发布于 2017-09-06 11:18:48
这是由于多态。
通常,如果您编写这样的方法:
private static void method(Fruit f) {}你可以用new Apple()来调用它
method(new Apple());对吗?因为Apple是Fruit的子类。
当您调用方法时:
writeExact(fruits, new Apple());由于您没有显式指定T,所以编译器试图推断它。它看到第一个参数fruits是一个List<Fruit>。它认为T一定是Fruit。现在,您的方法如下:
static void writeExact(List<Fruit> list, Fruit item)看见?将一个苹果传递给第二个参数是完全正确的,因为Apple是Fruit的一个子类。
另一方面,如果指定泛型T to be应用程序,则会发生以下错误:
List<Fruit> list = new ArrayList<>();
// compiler error!
GenericWriting.<Apple>writeExact(list, new Apple());因为List<Fruit>与List<Apple>不兼容。
https://stackoverflow.com/questions/46073344
复制相似问题