问题:
This question already has an answer here:
What is PECS (Producer Extends Consumer Super)? 12 answers
I got a problem ,eg :
Fruit Class
public...
可以将文章内容翻译成中文,广告屏蔽插件会导致该功能失效:
问题:
This question already has an answer here:
I got a problem ,eg :
Fruit Class
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 {
}
}
Food Class
public class Food {
}
Plate Class'
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;
}
}
I don't understand why
Plate<? super Fruit> plate = new Plate<>(new Food())
not error
but
plate.setItem(new Food())
is error
What is the difference between these two methods?
-that all, thanks!
回答1:
There are two things happening on this line:
Plate<? super Fruit> plate = new Plate<>(new Food());
new Plate<>(new Foo())
creates a new instance of Plate
. The generic parameter here is inferred to be Food
, so the right hand side creates a Plate<Food>
object.
The second thing is that this object is assigned to plate
. plate
can be a Plate<T>
as long as T
is Fruit
or a super class of Fruit
. Is Food
a superclass of Fruit
? Yes, so the right hand side can be assigned to plate
.
On this line however:
plate.setItem(new Food())
You are setting a plate's item. That plate
could be a plate of anything, as long as it is Fruit
or a superclass of Fruit
. This means that passing a Food
object wouldn't work. Why? Well, what if plate
is actually a Plate<Fruit>
? It could be, couldn't it? The compiler doesn't know.
So the only thing you can pass to plate.setItem
are Fruit
and subclasses of Fruit
.
回答2:
It is a classical case of PECS.
When using super
here, you created something that can get consumed but not produce anything to it of the type specified. This is exactly what you were trying to do.
To simplify it a bit, here is an example of what you could do with your object.
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)