英文:
Java Overriding Generic Methods
问题
为什么这个可以编译:
interface Test {
<T extends Integer> T getValue(T n);
}
class Impl implements Test{
public Integer getValue(Integer n) {
return n;
}
}
但是这个不能:
interface Test {
Integer getValue(Integer n);
}
class Impl implements Test{
public <T extends Integer> T getValue(T n){
return n;
}
}
它给我以下编译错误:
> Impl 不是抽象的,并且没有覆盖 Test 中的抽象方法 getValue(Integer)
>
> 错误: 名称冲突: Impl 中的 getValue(T) 和 Test 中的 getValue(Integer)
> 具有相同的擦除,但都没有覆盖另一个方法。
擦除不应该确保将 T 替换为 Integer 吗?
那么为什么第二个示例无效?
英文:
How come this compiles:
interface Test {
<T extends Integer> T getValue(T n);
}
class Impl implements Test{
public Integer getValue(Integer n) {
return n;
}
}
But this doesn't:
interface Test {
Integer getValue(Integer n);
}
class Impl implements Test{
public <T extends Integer> T getValue(T n){
return n;
}
}
It gives me the following compile error:
> Impl is not abstract and does not override abstract method
> getValue(Integer) in Test
>
> error: name clash: getValue(T) in Impl and getValue(Integer) in Test
> have the same erasure, yet neither overrides the other
Doesn't erasure ensure that T gets replaced with Integer?
So why would the second example not be valid?
答案1
得分: 7
你被允许用非泛型方法覆盖一个其签名是泛型方法擦除后的方法,但反过来则不行。这样做有一个很好的理由 - 允许超类型迁移到泛型,而不强制所有子类在同一天进行迁移。因此,编译器对已擦除的覆盖方法是宽容的。然而,在另一个方向上,你试图用泛型方法覆盖非泛型方法,这没有合理的迁移场景可以实现,这只会导致错误。
对于类也是如此;你可以编写:
class Foo<T> { }
class Bar extends Foo { }
但不可以编写:
class Foo { }
class Bar extends Foo<T> { }
英文:
You are allowed to override a generic method with a non-generic one whose signature is the erasure of the generic method, but not the other way around. There's a good reason for this -- to allow supertypes to migrate to generics without forcing all the subclasses to migrate on the same day. So the compiler is tolerant of erased overrides. In the other direction, though, you are trying to override a non-generic method with a generic one, and there's no reasonable migration scenario that could produce that -- it's just an error.
The same is true for classes; you can write
class Foo<T> { }
class Bar extends Foo { }
but not
class Foo { }
class Bar extends Foo<T> { }
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论