使用泛型覆盖方法的最简单示例

时间:2016-05-25 08:13:06

标签: java generics

我已经阅读了所有信息,但仍然无法找到原因,在这个基本示例中,覆盖是不可能的。请解释一下。

class Fruit{}
class Apple extends Fruit{}

class Parent {
    public Set<Fruit> getIt(){
     return null;
    }
}

class Child extends Parent {
    @Override // THIS DOESN'T WORK
    public Set<Apple> getIt(){
        return null;
    }
}

3 个答案:

答案 0 :(得分:2)

重写方法的返回类型必须是重写方法的返回类型的子类型。 Apple可能是Fruit的子类型,但Java泛型在类型参数中是不变的,因此这并不意味着Set<Apple>Set<Fruit>的子类型

否则你可以做以下事情:

Parent p = new Child();
Set<Fruit> fruitSet = p.getIt(); // actually a Set<Apple>
fruitSet.add(new Fruit());       // oops!

您可以使用类型边界来解决此问题:

class Parent {
    public Set<? extends Fruit> getIt() {
        return null;
    }
}

class Child extends Parent {
    @Override
    public Set<Apple> getIt(){
        return null;
    }
}

答案 1 :(得分:2)

因为它没有超越。你想要的是协方差。这意味着您希望将子类Set<Apple>的重写方法的返回类型Child用作类Set<Fruit>的原始方法Parent的返回类型的子类型

但是,唉,Set<Apple>不是Java中Set<Fruit>的子类型,即使AppleFruit的子类型。原因很简单:如果FruitSet<Fruit>,您可以向Set<Apple>添加任何Set<Fruit>,然后您就可以添加Banana a Set<Apple>因为超类中的任何可能在子类中都是可能的......

因此Set<Fruit>Set<Apple>是不相关的类型,这禁止覆盖。

答案 2 :(得分:0)

class Fruit{}
class Apple extends Fruit{}

class Parent {
    public Set<? extends Fruit> getIt(){
        return null;
    }
}

class Child extends Parent {
    @Override // THIS DOESN'T WORK
    public Set<Apple> getIt(){
        return null;
    }
}

但是因为一个类不是它自己的子类,所以最好将水果子类化为另一个类(如SuperFruit)并在父getIt()方法中使用它而不是Fruit