首页 文章

java泛型多态性

提问于
浏览
2

在下面的代码中

public class Animal {

    public void eat() {
        System.out.println("Animal eating");
    }
}

public class Cat extends Animal {

    public void eat() {
        System.out.println("Cat eating");
    }

}

public class Dog extends Animal {

    public void eat() {
        System.out.println("Dog eating");
    }
}

public class AnimalFeeder {
    public void feed(List<Animal> animals) {
        animals.add(new Cat());
        animals.forEach(animal -> {
            animal.eat();
        });
    }

    public static void main(String args[]){
        List<Animal> a = new ArrayList<Animal>();
        a.add(new Cat());
        a.add(new Dog());

        new AnimalFeeder().feed(a);
     /* List<Dog> dogs = new ArrayList<>();
        dogs.add(new Dog());
        dogs.add(new Dog());
        new AnimalFeeder().feed(dogs); // not allowed
        */


    }
}

我知道feed (List<Animal> animals) 方法不能传递 List<Dog>, List<Cat> 等 . 如果允许 List<Dog> ,那么也可以添加 animals.add(new Cat()); ,这是不可取的,因为在运行时类型擦除 . 所以只允许 List<Animal> .

但是,我可以做到以下几点

List<Animal> a = new ArrayList<Animal>();
        a.add(new Cat());
        a.add(new Dog());
and still call new AnimalFeeder().feed(a);

当我运行程序时,它给了我

Cat eating
Dog eating
Cat eating

我对多态通用概念的理解是“我们希望我们的 List<Animal> 只接受 List<Animal> ,并且该列表仅包含动物,而不包含猫或狗,换句话说只包含动物” . 不想要任何其他包含狗或猫的东西吗?是对的吗?如果是的话,为什么我允许传递包含狗,猫等的 List<Animal> . 这与传递(假设允许) List<Dog> 然后将 new Cat() 添加到狗列表不一样吗?

我希望我的问题很明确 .

我确实经历了Is List<Dog> a subclass of List<Animal>? Why are Java generics not implicitly polymorphic?

但我能找到问题的答案吗?

谢谢,

2 回答

  • 8

    我对多态通用概念的理解是“我们希望我们的List只接受List

    真正

    以及该列表仅包含动物,而不包含猫或狗

    不对

    List<Animal> 可以包含 Animal 类的实例以及扩展 Animal 的任何类的实例 . DogCat 都是 Animal s,因此它们可以添加到 List<Animal> .

    另一方面,当您使用类型 List<Dog> 时,您告诉编译器您的 List 应该只包含 Dog 实例(或 Dog 的子类实例),因此这样的 List 不能包含 Cat .

  • 3

    我们不要先将自己与泛型混淆 . 考虑一下:

    Animal cat = new Cat();
    

    这是允许的,因为 CatAnimal .

    换句话说, Animal 类型的变量可以保存任何对象的引用,该对象是 Animal 或其子类 .

    回到泛型:

    List<Animal> animals = new ArrayList<>();
    

    animalsList ,可以容纳任何类型的 Animal 及其子类,类似于之前发生的情况 .

    泛型和非泛型情况之间的区别在于,通用仅在编译时确保类型 - 类型在运行时被擦除,因此 List<Animal> 在运行时等效于 List<Object> .

相关问题