以下代码无法编译,但是,如果我将f(对象)更改为f(String)或f(整数),则编译。 我已经阅读了关于这个主题的其他帖子,但我仍然没有得到它,为什么编译器不知道使用哪种方法 (如果是新实例A a = new B();)
public class SampleTester {
public static class A {
public void f(int x) { System.out.print("1"); }
public void f(Object x) { System.out.print("2"); }
}
public static class B extends A {
public <T> void f(T x) { System.out.print("3"); } //compiler error
}
public static void main(String[] args) {
A a = new A();
B b= new B();
a.f(3);
a.f("foo");
b.f(3);
b.f("foo");
}
}
如果我将T x
更改为Object t
,它仍然无法编译,那么有什么区别?此外,为什么它不只是覆盖A的功能? (在类型擦除后两者都具有相同的签名
答案 0 :(得分:3)
类B
扩展A
,因此继承了A
中存在的所有方法。这意味着B
将有3种方法:
public void f(int x)
public void f(Object x)
public <T> void f(T x)
问题是f(T x)
将在编译期间进行类型擦除,T
将替换为Object
,从而导致重复方法,因为您已经有一个方法需要Object
论点。
要解决此问题,请删除采用Object
参数的方法或提供T
的上限。 (示例T extends Number
,以便在类型删除期间T
替换为Number
解决您的评论(我现在已添加到您的问题中):
public <T> void f(Object x)
无法编译,因为它不是来自public void f(Object x)
的{{1}}的有效覆盖。
方法A
属于子类,可以使用superlcass引用作为public <T> void f(Object x)
或a.<Integer>f(null);
进行调用。由于overriden方法在运行时解析 BUT 泛型在编译时自行进行类型擦除,因此编译器无法知道是否用a.<String>f(null);
替换T
或{ {1}}在编译时。
由于编译器具有必要的所有信息,因此在Integer
中使用方法String
和在public <T> void f(Object x)
中使用方法A
来反转方法仍然是合法的。决定应该用public void f(Object x)
代替什么。