java Some usage questions about “? super Fruit” [duplicate]

问题: 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)
  • 发表于 2019-02-28 17:43
  • 阅读 ( 163 )
  • 分类:sof

条评论

请先 登录 后评论
不写代码的码农
小编

篇文章

作家榜 »

  1. 小编 文章
返回顶部
部分文章转自于网络,若有侵权请联系我们删除