如果重写方法没有,为什么重写方法不能指定类型参数?
Why can't overriding methods specify a type parameter if the overriden method doesn't?
以下代码无法编译,但是,如果我将 f(object) 更改为 f(String) 或 f(Integer),它会编译。
我已经阅读了有关该主题的其他帖子,但我仍然不明白,为什么编译器不知道使用哪种方法
(如果是新实例 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 中的函数? (两者在类型擦除后具有相同的签名
class 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
在 type-erasure 期间被替换为 Number
)
解决您的评论(我现在已将其添加到您的问题中):
public <T> void f(Object x)
无法编译,因为它不是来自 A
的 public void f(Object x)
的有效覆盖。
方法public <T> void f(Object x)
属于子class,可以使用超类引用作为a.<Integer>f(null);
或a.<String>f(null);
调用。由于覆盖方法在运行时解析 BUT 泛型在编译时本身会经历类型擦除,编译器无法知道是否用 [=31= 替换 T
] 或 String
在编译时。
反转方法仍然是合法的,这样你在A
中有方法public <T> void f(Object x)
,在B
中有方法public void f(Object x)
,因为编译器有所有决定 <T>
应该被替换的必要信息。
以下代码无法编译,但是,如果我将 f(object) 更改为 f(String) 或 f(Integer),它会编译。 我已经阅读了有关该主题的其他帖子,但我仍然不明白,为什么编译器不知道使用哪种方法 (如果是新实例 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 中的函数? (两者在类型擦除后具有相同的签名
class 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
在 type-erasure 期间被替换为 Number
)
解决您的评论(我现在已将其添加到您的问题中):
public <T> void f(Object x)
无法编译,因为它不是来自 A
的 public void f(Object x)
的有效覆盖。
方法public <T> void f(Object x)
属于子class,可以使用超类引用作为a.<Integer>f(null);
或a.<String>f(null);
调用。由于覆盖方法在运行时解析 BUT 泛型在编译时本身会经历类型擦除,编译器无法知道是否用 [=31= 替换 T
] 或 String
在编译时。
反转方法仍然是合法的,这样你在A
中有方法public <T> void f(Object x)
,在B
中有方法public void f(Object x)
,因为编译器有所有决定 <T>
应该被替换的必要信息。