14

假设我们有一些这样的测试接口/类:

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.eat是一个带有约束的泛型方法。现在我的Human课是这样的:

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

编译得很好。您可以看到,由于接口丢失,因此受到的Human.eat限制更少。Animal.eatEatable

Q1:为什么编译器不抱怨这种不一致?

Q2:如果编译器可以接受Plant&Eatable 降级,为什么会抱怨?Planteat(Object plant)

4

2 回答 2

12

课程:Gilad Bracha 认为的 泛型

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);因此当您覆盖它时,编译器不会抱怨

于 2016-08-10T03:32:12.940 回答
0

Ahmed 的回答是对的,顺便说一句,如果你想约束 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
于 2016-08-13T07:30:25.437 回答