我遇到问题,例如:
水果类
public class Fruit extends Food {
public static void main(String[] args) {
Plate<? super Fruit> plate = new Plate<>(new Food());
plate.setItem(new Apple());
plate.setItem(new Food());
}
static class Apple extends Fruit {
}
}
食品课
public class Food {
}
盘子类'
public class Plate<T> {
private T item;
public Plate(T t) {
item = t;
}
public T getItem() {
return item;
}
public void setItem(T item) {
this.item = item;
}
}
我不明白为什么
Plate<? super Fruit> plate = new Plate<>(new Food())
没有错误
但是
plate.setItem(new Food())
是错误
这两种方法有什么区别?
-谢谢!
答案 0 :(得分:1)
此行发生了两件事:
Plate<? super Fruit> plate = new Plate<>(new Food());
new Plate<>(new Foo())
创建一个Plate
的新实例。推断此处的通用参数为Food
,因此右侧会创建一个Plate<Food>
对象。
第二件事是将该对象分配给plate
。只要plate
是Plate<T>
,T
可以是Fruit
或Fruit
的超类。 Food
是Fruit
的超类吗?是的,因此可以将右侧分配给plate
。
但是在这一行:
plate.setItem(new Food())
您正在设置印版的项目。 plate
可以是任何事物的盘子,只要它是Fruit
或Fruit
的超类即可。这意味着无法传递Food
对象。为什么?好吧,如果plate
实际上是Plate<Fruit>
怎么办?可能是,不是吗?编译器不知道。
因此,您唯一可以传递给plate.setItem
的是Fruit
和Fruit
的子类。
答案 1 :(得分:1)
这是PECS的经典案例。
在此处使用super
时,您创建了一些可以消耗但无法产生指定类型的东西的东西。这正是您想要做的。
为简化起见,下面是您可以对对象进行处理的示例。
Plate<? super Fruit> plate = new Plate<>(...);
Fruit fruit = plate.getItem(); // GOOD !
Food food = plate.getItem(); // GOOD ! Because even a Fruit can be assigned to a Food reference so it's OK !
Apple apple = plate.getItem(); // BAD ! No insurance it is an apple, we just know it is a Fruit
plate.setItem(new Fruit()); // GOOD !
plate.setItem(new Apple()); // GOOD ! Because we know it's always a Fruit, and Apple extends Fruit
plate.setItem(new Food()); // BAD ! No insurance we're not dealing with a Fruit, and a Food object can't be assigned to a Fruit reference (without casting)