普通消费者

时间:2018-04-06 20:33:04

标签: java generics consumer

尝试与消费者一起理解泛型。

msg='This %(key1)s contains custom %(key2)s'
dict={'key1':'string','key2':'placeholders'}
print(msg%dict)

>> This string contains custom placeholders

我收到编译错误:

class Fruit{}
class Apple extends Fruit{}
class Orange extends Fruit{}

class Util{
    private Collection<Apple> appleList = new ArrayList<>();

    public Util(){
        acceptFruit(ap -> appleList.add(ap);
    }

    public <T extends Fruit> void acceptFruit(Consumer<T> fruitConsumer){
        //FruitService.getAllFruits();
        //some validations and get fruit object
        fruitConsumer.accept(fruit);
    }
}

//Some other class calling Util.acceptFruit(orange -> oranges.add(orange);

以及:

acceptFruit(ap -> appleList.add(ap);
add (Apple) in Collection can not be applied to (Fruit)

由于fruit.accept(fruit); accept (T) in Consumer cannot be applied to (Apple) 正在延长Apple,我不明白为什么会收到此错误?关于泛型/消费者概念中缺少什么的任何想法?

3 个答案:

答案 0 :(得分:3)

Apple可能是Fruit,但Collection<Apple> a Collection<Fruit>。这是由于泛型类型的不变性。

忽略acceptFruit内部的编译错误(对我来说完全不清楚你开始做什么),最好的方法是确保你的集合包含你要与之交互的超类任何子类。

 private Collection<Fruit> fruitList = new ArrayList<>();

这样,您可以在消费者中消费您想要的任何水果。

比这更先进的东西 - 也就是说,消费特定种类的水果 - 比我们这里的基本仿制药更先进,最好留给读者练习。

答案 1 :(得分:0)

AppleFruit的子类型,但不知道AppleT的子类型,它是未知类型T可以是FruitOrangeBanana,一般来说Apple不能是所有这些的子类型。

宣布acceptFruit方法的方式并不真正有意义,因为作为一种通用方法,这意味着无论T是什么,它都必须正常工作。 acceptFruit的来电者可以通过T来调用它,无论来电者想要什么,acceptFruit必须正常正常工作,而不知道T是什么。因此acceptFruit接受一个参数Consumer,但acceptFruit在运行时并不知道Consumer想要什么类型 - 它可能是{{1}一次调用,以及Consumer<Apple>下一次调用 - 但Consumer<Orange>无法推断特定调用中需要的类型,因为它没有任何其他参数可以告诉它是什么。为了调用acceptFruit,它需要传入一个未知类型的实例。因此fruitConsumer可以安全编写的唯一方法是:1)它根本不会调用acceptFruit;或者2)它总是将fruitConsumer传递给null

答案 2 :(得分:-1)

您的acceptFruit()很奇怪,因为它会调用fruit.accept(fruit)。此代码将消费者自身作为参数调用,这会引起泛型中的所有混乱。你必须将apple的实例传递给消费者,所以这里是你的代码没有错误:

class Util {
    private Collection<Apple> appleList = new ArrayList<>();

    public Util(){
        acceptFruit(ap -> appleList.add(ap), new Apple());
    }

    public <T extends Fruit> void acceptFruit(Consumer<T> fruitConsumer, T fruit){
        //FruitService.getAllFruits();
        //some validations and get fruit object
        fruitConsumer.accept(fruit);
    }
}