有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

如何在java中重写泛型列表返回类型

我试图重写在子类中返回type as list的方法,如下例所示,由于泛型问题,我无法在我的子类中这样做。我无法更改我的超级类代码,因此如何解决该问题?任何人都可以指引我。。。非常感谢

无法更新的超类:

public class Animal {
           private String legs;
    }

public class TestSuper {

    public List<Animal> addAnimals() {
        return animals;
    }
}

子类:

public class Dog extends Animal {
         private String sound;
    }

public class TestSub extends TestSuper {

    public List<Dog> addAnimals() { --> I need to override this method but want return type as List of dogs
        return null;
    }
}

共 (5) 个答案

  1. # 1 楼答案

    如果DogAnimal的一个子类,您可能会这样做

    以下签名:

    public List<? extends Animal> addAnimals()
    

    那就去吧

    public List<Dog> addAnimals()
    

    在班级里

    或者你可以让超类成为泛型<T>和实现类<Dog>

  2. # 2 楼答案

    不能将列表的泛型类型更改为该泛型类型的子类型。问题是,对任何实例的引用都可能是该实例的子类型。让我们看看这个例子

    SuperType sup = new SubType();
    sup.getAnimals().add(new Cat());
    //adding cat is possible because getAnimals() returns List<Animal>
    

    因此,您将Cat添加到只应包含Dogs的列表中,这是错误的


    同样,在Overrided方法中,您不能将列表的泛型类型更改为具有该泛型类型的超类型的列表(如List<Dog>List<Animal>)。为什么?让我们看看这个例子

    SuperType sup = new SubType();
    Dog d = sup.getAnimals().get(0);
    

    在亚型中,我们有动物列表,所以有可能get(0)会返回猫


    如果你能在你的类中修改代码,那么试试这种方法

    class Super<T extends Animal> {
        public List<T> addAnimals() {
            return null;
        }
    }
    
    class Sub extends Super<Dog> {
    
        @Override
        public List<Dog> addAnimals() {
            return null;
        }
    }
    
  3. # 3 楼答案

    如果超级类真的不能更新,恐怕你就是不能

    如果您能够更新超级类:

    TestSuper中,必须使用public List<? extends Animal> addAnimals()而不是public List<Animal> addAnimals()

    您还有什么其他解决方案:

    您可以使用这样一种实用方法:

    @SuppressWarnings("unchecked")
    public static <T extends Animal> List<T> cast(List<Animal> animals, Class<T> subclass) {
        List<T> out = new ArrayList<T>();
        for (Animal animal : animals) {
            if (!subclass.isAssignableFrom(animal.getClass())) {
                // the "animal" entry isn't an instance of "subclass"
                // manage this case however you want ;)
            } else {
                out.add((T) animal);
            }
        }
        return out;
    }
    

    然后,打电话:

    List<Dog> dogs = TheClassNameYouChose.cast(animals, Dog.class);
    
  4. # 4 楼答案

    这是不可能的。super class合同规定,如果您有:

    class Animal {}
    class Dog extends Animal {}
    class Cat extends Animal {}
    

    以下代码必须有效:

    TestSuper test = new AnySubclassOfTestSuper(); // including TestSub!
    test.addAnimals().add(new Cat());
    

    您在TestSub类中的重写将违反这一点,因为您无法将Cat添加到List<Dog>。因为这违反了面向对象类型系统的一个基本原则,所以你不会找到一个完美的解决方法来解决这个限制

    将超类更改为使用List<? extends Animal>的建议会起作用,因为您无法向该列表中添加任何内容

  5. # 5 楼答案

    您需要让TestSuper使用泛型来真正正确地工作

    TestSuper<T extends Animal> {
    
      public List<T> addAnimals() {
    
      }
    }
    
    TestSub extends TestSuper<Dog> {
    
    
    }