Java 具有仿制药的消费者

Java 具有仿制药的消费者,java,generics,consumer,Java,Generics,Consumer,试图与消费者一起理解泛型 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); } p

试图与消费者一起理解泛型

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);

fruit.accept(fruit);
accept (T) in Consumer cannot be applied to (Apple)
由于
Apple
正在扩展
Fruit
,我不明白为什么会出现这个错误?你知道我在泛型/消费者概念中遗漏了什么吗?

你的
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);
    }
}
class-Util{
私有集合appleList=new ArrayList();
公共Util(){
acceptFruit(ap->appleList.add(ap),newapple());
}
公共水果(消费水果消费者,T水果){
//getAllFruits();
//一些验证和获取水果对象
水果消费者。接受(水果);
}
}
您的
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);
    }
}
class-Util{
私有集合appleList=new ArrayList();
公共Util(){
acceptFruit(ap->appleList.add(ap),newapple());
}
公共水果(消费水果消费者,T水果){
//getAllFruits();
//一些验证和获取水果对象
水果消费者。接受(水果);
}
}

苹果
可能是
水果
,但
集合
不是集合
。这是由于泛型类型的不变性

忽略
acceptFruit
内部的编译错误(我完全不清楚您首先要做什么),最好的方法是确保集合包含要与之接口的超类,而不是任何子类

 private Collection<Fruit> fruitList = new ArrayList<>();
private Collection foultlist=new ArrayList();
这样,你可以在你的消费者身上食用任何你想要的水果


任何比这更高级的东西——也就是说,食用特定种类的水果——都比我们这里的基本仿制药更高级,最好留给读者作为练习。

Apple
可能是
水果
,但
Collection
而不是
Collection
。这是由于泛型类型的不变性

忽略
acceptFruit
内部的编译错误(我完全不清楚您首先要做什么),最好的方法是确保集合包含要与之接口的超类,而不是任何子类

 private Collection<Fruit> fruitList = new ArrayList<>();
private Collection foultlist=new ArrayList();
这样,你可以在你的消费者身上食用任何你想要的水果


任何比这更高级的东西——也就是食用特定种类的水果——都比我们这里的基本泛型更高级,最好留给读者作为练习。

Apple
水果的子类型,但是
Apple
不知道是
T
的子类型,这是一种未知类型
T
可以是
水果
,或
橙色
,或
香蕉
,通常
苹果
不能是所有这些的子类型


声明
acceptFruit
方法的方式没有真正意义,因为作为一个通用方法,这意味着无论
t
是什么,它都必须工作。
acceptFruit
的调用者可以使用调用者想要的
T
来调用它,并且
acceptFruit
必须在不知道
T
是什么的情况下正常工作。因此,
acceptFruit
接受一个参数,
Consumer
,但是
acceptFruit
在运行时不知道
Consumer
想要什么类型——它可能是
Consumer
一个调用,而
消费者
下一个调用--但是
acceptFruit
无法推断特定调用中需要什么类型,因为它没有任何其他参数来告诉它它是什么。为了调用
fruitConsumer
,它需要传入一个未知类型的实例。因此,
acceptFruit
可以安全编写的唯一方法是:1)它根本不调用
fruitConsumer
;或者2)它总是将
null
传递到
fruitConsumer

Apple
Fruit
的子类型,但是
Apple
不知道是
T
的子类型,这是一个未知类型
T
可以是
水果
,或
橙色
,或
香蕉
,通常
苹果
不能是所有这些的子类型

声明
acceptFruit
方法的方式没有真正意义,因为作为一个通用方法,这意味着无论
t
是什么,它都必须工作。
acceptFruit
的调用者可以使用调用者想要的
T
来调用它,并且
acceptFruit
必须在不知道
T
是什么的情况下正常工作。因此,
acceptFruit
接受一个参数,
Consumer
,但是
acceptFruit
在运行时不知道
Consumer
想要什么类型——它可能是
Consumer
一个调用,而
消费者
下一个调用--但是
acceptFruit
无法推断特定调用中需要什么类型,因为它没有任何其他参数来告诉它它是什么。为了调用
fruitConsumer
,它需要传入一个未知类型的实例。因此,
acceptFruit
可以安全编写的唯一方法是:1)它根本不调用
fruitConsumer
;或者2)它总是将
null
传递到
fruitConsumer

阅读(或者)。