Java泛型方法重写编译错误咨询:带泛型参数方法报错原因
get2() Fails to Override While get1() Works Let's break down this confusing behavior, starting with the core rules of Java generic method overriding.
First, Some Background on Generic Overrides
When you override a generic method, Java's compiler checks two key things:
- The subclass method's signature must be a subsignature of the superclass method (same name, matching parameter types—even after type erasure).
- If the subclass method isn't generic, the compiler has to infer the superclass's type parameters to ensure the return type is compatible (either via valid subtyping or an allowed unchecked conversion).
Why get1() Works (With a Warning)
Your get1() superclass method is <X> R<X> get1()—a generic method with no parameters. When you override it with R<Object> get1():
- The compiler infers
X = Objectto align the return types (sinceR<Object>exactly matchesR<X>whenXisObject). - The catch here is that the superclass method promises to return any
R<X>(for whateverXthe caller requests), but your subclass only returnsR<Object>. This breaks the method's contract, but since Java can't enforce this at runtime (thanks to type erasure), it just issues an unchecked warning instead of blocking it.
Why get2() Throws a Compile Error
Your get2() superclass method is <Y> R<Y> get2(Collection<String> p)—a generic method with a parameter of a concrete parameterized type (Collection<String>). When you try to override it with R<Double> get2(Collection<String> p):
- Even though the parameter types match exactly, the compiler hits a roadblock when inferring the
Ytype parameter. The presence of a concrete parameterized type in the method parameters triggers a stricter check: the compiler expects the subclass method to either explicitly redeclare the generic type parameter (likeget3()does) or use a wildcard return type (e.g.,R<?>) that works with all possibleR<Y>instances. - Since your subclass method does neither, the compiler rejects it with the error that it doesn't override a supertype method.
Why get3() Compiles (With a Warning)
Your get3() method redeclares the generic type parameter (<Object> R<Object> get3(...)), which makes it a valid generic override. The warning you see ("The type parameter Object is hiding the type Object") is just a naming issue—you used Object as the type parameter name, which shadows the built-in java.lang.Object class. Rename it to something like <V> (as in your second snippet), and the warning goes away.
Fixing get2()
To resolve the compile error while keeping your method-specific type flexibility, redeclare the generic type parameter in the subclass:
@Override public <Y> R<Y> get2(Collection<String> p) { // Your implementation here return null; }
If you specifically need to return a concrete type like R<Double>, you'd have to adjust the superclass method's contract (e.g., use a fixed type parameter or wildcard), but since you want independent types per method, redeclaring the generic parameter is the right approach.
内容的提问来源于stack exchange,提问作者Julian Sommerfeldt

