为什么接口的泛型方法可以在Java中实现为非泛型?

2022-09-04 03:29:27

假设我们有一些测试接口/类,如下所示:

abstract class Plant {
    public abstract String getName();
}

interface Eatable { }

class Apple extends Plant implements Eatable {
    @Override
    public String getName() {
        return "Apple";
    }
}

class Rose extends Plant {
    @Override
    public String getName() {
        return "Rose";
    }
}

interface Animal {
    <T extends Plant & Eatable> void eat(T plant);
}

您可以看到是一个具有约束的泛型方法。现在我有我的班级是这样的:Animal.eatHuman

class Human implements Animal {
    @Override
    public void eat(Plant plant) {
    }
}

编译良好。您可以看到比界面丢失的限制要少。Human.eatAnimal.eatEatable

问题 1:为什么编译器不抱怨这种不一致?

问题 2:如果降级为编译器可以接受,为什么它会抱怨 ?Plant&EatablePlanteat(Object plant)


答案 1

教训:根据他的说法,吉拉德·布拉查的仿制药

public static <T extends Object & Comparable<? super T>> T max(Collection<T> coll)

这是一个使用语法 T1 和 T2 为类型参数提供多个边界的示例...& Tn.已知具有多个边界的类型变量是绑定中列出的所有类型的子类型。使用多重绑定时,绑定中提到的第一个类型将用作类型变量的擦除。

所以你的例子将被删除,所以当你覆盖它时,编译器不会抱怨<T extends Plant & Eatable> void eat(T plant);void eat(Plant plant);


答案 2

艾哈迈德的答案是对的,顺便说一句,如果你想把约束的实现放在Animal的接口上,你应该这样声明:

interface Animal<T extends Plant & Eatable>  {
    void eat(T plant);
}

然后,如果在不提供类型信息的情况下实现 Animal 接口,编译器将使用最小意外策略将 T 推断为 Plant 类型。但是,如果您提供必要的类型信息,编译器将正常工作。

class Human implements Animal<Rose> // won't compile
class Human implements Animal<Apple> // compile

推荐