Java中泛型方法能否重写父类非泛型方法?实例答疑
Java泛型方法与重写的两个常见问题解答
场景一:子类泛型方法为何未覆盖父类非泛型方法
代码示例
父类与子类代码:
class A123 { public void foo(String str) { System.out.println("1"); } } class B123 extends A123 { public <T> void foo(T item) { System.out.println("2"); } }
调用代码:
public class Test123 { public static void main(String[] args){ B123 b = new B123(); b.foo("test"); } }
原因分析
核心问题是泛型方法和非泛型方法的签名不匹配,无法构成重写:
- 父类的
foo是明确接收String类型参数的非泛型方法,方法签名为foo(String)。 - 子类的
foo是带类型参数<T>的泛型方法,签名为foo(T)(编译期类型擦除后是foo(Object),但重写检查基于编译时签名)。 - 即使调用时编译器推断
T=String,两个方法的签名依然不同——子类方法属于重载而非重写。 - 编译器解析调用时会优先选择最精确匹配的方法:父类继承来的
foo(String)比泛型方法foo(T)更匹配String类型参数,因此最终调用父类方法,打印1。
场景二:子类非泛型方法为何未覆盖父类泛型方法
代码示例
父类与子类代码:
class A123 { public <T>void foo(T item) { System.out.println("1"); } } class B123 extends A123 { public void foo(String str) { System.out.println("2"); } }
调用代码:
public class Test123 { public static void main(String[] args){ A123 b = new B123(); b.foo("test"); } }
原因分析
重写的核心要求是方法签名(包括泛型声明)完全一致:
- 父类的
foo是泛型方法,签名包含类型参数<T>,表示可接收任意类型参数。 - 子类的
foo是接收String参数的非泛型方法,签名为foo(String),和父类的foo(T)不匹配,因此是重载而非重写。 - 当用父类引用调用方法时,编译期会根据父类的方法签名解析调用,此时编译器推断
T=String,调用父类的泛型方法,打印1。若要实现重写,子类方法也必须声明为泛型方法:public <T> void foo(T item)。
内容的提问来源于stack exchange,提问作者Leah Golub
相关产品推荐
相关产品推荐

