首页 > 解决方案 > 如何类型安全地将元素添加到泛型扩展类并实现接口的列表中?

问题描述

我正在寻找一种类型安全、经过检查的解决方案,以将元素添加到其泛型同时需要类和接口的列表中。该示例说明了我想做的事情 - 将其类型Cat扩展Animal并实现的对象添加Quadruped到列表List<T>where T extends Animal & Quadruped.

class Example {
    public interface Quadruped { };
    public static class Animal { };
    public static class Cat extends Animal implements Quadruped { };

    public <T extends Animal & Quadruped> List<T> getQuadrupedAnimals(){
        List<T> result = new ArrayList<>();
        Cat cat = new Cat();
        result.add(cat); // compile error
        return result;
    }
}

当然,强制转换catB将解决编译错误,但这将是未经检查的。

有什么解决方案吗?如果没有,有谁知道编译器不允许这样做的原因?

标签: javagenerics

解决方案


有谁知道编译器不允许这样做的原因?

T特定的Animal 和 Quadraped,在 的调用站点选择getQuadrupedAnimals()

该方法的合法调用包括:

List<Dog> listOfDogs = getQuadrupedAnimals();
List<Hamster> listOfHamsters = getQuadrupedAnimals();

因此您不能将 aCat放入该列表(也不能放入 aDog或 a Hamster,就此而言),因为您放入的任何内容都可能无法转换为调用者想要的类型。(不过,您可以将文字null放在列表中)。

解决方案是将返回类型声明为List<Cat>(or List<? extends Cat>, or List<? super Cat>),如果要返回包含Cats 的列表。


交集类型只有在参数中使用时才真正有用,例如

public <T extends Animal & Quadruped> List<T> getQuadrupedAnimals(T animal){
  return List.of(animal);
}

或者

public <T extends Animal & Quadruped> int countLegs(List<T> animals){
  return 4 * animals.size();
}

推荐阅读