Java 重写泛型方法

huangapple go评论87阅读模式
英文:

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 {
    &lt;T extends Integer&gt; 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 &lt;T extends Integer&gt; 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&lt;T&gt; { }
class Bar extends Foo { }

but not

class Foo { }
class Bar extends Foo&lt;T&gt; { }

huangapple
  • 本文由 发表于 2020年7月25日 08:33:07
  • 转载请务必保留本文链接:https://go.coder-hub.com/63083062.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定