带抽象类的构造函数 - 不接受具体的

时间:2015-01-14 11:56:49

标签: java

我有一个抽象类Animal,有扩展的马和猪类。我还有一个Farm类和该类中的构造函数,我想用它来填充Animal在Farm中的列表。但编译器显示错误。

我将列出Farm类,因为我认为这将说明问题而无需列出整个事情:

import java.util.ArrayList;


public class Farm {
    public ArrayList<Animal> farmlist;
    { 
        System.out.println("Initializing the farmlist...");
        farmlist = new ArrayList<>();
        farmlist.add(new Horse()); // There will always be a Horse in the farm.
    }

    public Farm() {
        System.out.println("Blank constructor called..");

    }

    public Farm(Animal animal, int n) {
        System.out.println("Multiple animal constructor called...");
        for (int i = 1; i <= n; i++) {
            farmlist.add(new animal());
        }
    }
}

最后一行代码给出了编译器错误,它似乎不允许我传入类型Pig,例如,如果我想。这个想法是它会添加我传入farmlist的任何类型的多种动物。我无法理解为什么它不会让我这样做或我需要什么方式&#34;短语&#34;我想做什么。

1 个答案:

答案 0 :(得分:5)

  

这个想法是它会添加多种我传入farmlist的动物。

在这种情况下,您需要传递Animal类型 - 而不是对Animal实例的引用,就是你现在正在做的事情。我怀疑你真的想要这样的东西:

public Farm(Class<? extends Animal> animalType, int n)
       throws ReflectiveOperationException {
    System.out.println("Multiple animal constructor called...");
    for (int i = 0; i < n; i++) {
        farmlist.add(animalType.newInstance());
    }
}

这将尝试在您传入的任何类型上调用可访问的无参数构造函数,n次。你会这样称呼它:

Farm farm = new Farm(Pig.class, 10);

另一个选项(最适合Java 8+)将传入一个创建新动物的函数。例如:

public Farm(Supplier<? extends Animal> supplier, int n) {
    for (int i = 0; i < n; i++) {
        farmlist.add(supplier.get());
    }
}

然后用:

来调用它
Farm farm = new Farm(() -> new Pig(), 10);

请注意,如果您使用原始签名的kocko答案,则最终不会有多个独立的动物对象 - 最终您的列表中包含对相同动物对象的多个引用。了解对象和引用如何在Java中工作非常重要 - 而且它可能是从一本好书或教程中学到的最好的东西。