为什么接口的泛型方法可以在 Java 中实现为非泛型?
Why a generic method of an interface can be implemented as non-generic in Java?
假设我们有一些这样的测试interfaces/classes:
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 是这样的:
class Human implements Animal {
@Override
public void eat(Plant plant) {
}
}
编译正常。您可以看到 Human.eat
比 Animal.eat
受到的限制更少,因为 Eatable
接口丢失了。
问题 1:为什么编译器不抱怨这种不一致?
Q2:如果编译器可以接受 Plant&Eatable
降级 到 Plant
,为什么它会抱怨 eat(Object plant)
?
Lesson: Generics by Gilad Bracha
据他说
public static <T extends Object & Comparable<? super T>> T max(Collection<T> coll)
This is an example of giving multiple bounds for a type parameter,
using the syntax T1 & T2 ... & Tn. A type variable with multiple
bounds is known to be a subtype of all of the types listed in the
bound. When a multiple bound is used, the first type mentioned in the
bound is used as the erasure of the type variable.
因此您的示例 <T extends Plant & Eatable> void eat(T plant);
将被擦除为 void eat(Plant plant);
因此当您覆盖它时编译器不会抱怨
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
假设我们有一些这样的测试interfaces/classes:
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 是这样的:
class Human implements Animal {
@Override
public void eat(Plant plant) {
}
}
编译正常。您可以看到 Human.eat
比 Animal.eat
受到的限制更少,因为 Eatable
接口丢失了。
问题 1:为什么编译器不抱怨这种不一致?
Q2:如果编译器可以接受 Plant&Eatable
降级 到 Plant
,为什么它会抱怨 eat(Object plant)
?
Lesson: Generics by Gilad Bracha 据他说
public static <T extends Object & Comparable<? super T>> T max(Collection<T> coll)
This is an example of giving multiple bounds for a type parameter, using the syntax T1 & T2 ... & Tn. A type variable with multiple bounds is known to be a subtype of all of the types listed in the bound. When a multiple bound is used, the first type mentioned in the bound is used as the erasure of the type variable.
因此您的示例 <T extends Plant & Eatable> void eat(T plant);
将被擦除为 void eat(Plant plant);
因此当您覆盖它时编译器不会抱怨
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