泛型方法不覆盖超类中的类似泛型方法 -> 使用哪个?
Generic method not overriding similar generic method in superclass -> Which one is used?
鉴于这种情况:
public class Animal {
public <T> void genericMethod(T t){
System.out.println("Inside generic method on animal with parameter " + t.toString());
}
}
public class Cat extends Animal {
public <T extends Cat> void genericMethod(T t){
System.out.println("Inside generic method on cat with parameter " + t.toString());
}
}
public class Main {
public static void main(String[] args) {
Animal animal = new Animal();
Cat cat = new Cat();
cat.genericMethod(cat);
}
}
class Cat
中的方法 genericMethod()
绝对不会覆盖 superclass 方法(如果我添加 @Override
签名,编译器会报错)这是合理的,因为对类型 T
的要求不同。
但是我不太明白,编译器是如何决定在main方法中调用cat.genericMethod(cat)
这两个方法中的哪一个。因为实际上这两种方法都是可见的,都是适用的。我本以为会出现像 "ambigous function call" 这样的编译器错误。有人可以解释这种行为吗?
由于子class方法的通用类型绑定,这两个方法具有不同的擦除。
对于超级 class 方法,擦除是:
public void genericMethod(Object t)
对于子 class 方法,擦除是:
public void genericMethod(Cat t)
方法重载解析规则选择参数最匹配的方法。因此,当您传递 Cat
参数时,会选择第二种 (sub-class) 方法。
Java,在编译时,会选择most specific matching method。
在您的示例中,这意味着该方法的 Cat
实现。
有两点需要注意:
- 如果你传递给它一个
Animal
,很明显只会使用在Animal中声明的方法(因为它不符合T extends Cat
约束)。
如果你传递给它 Cat
:
- Java 决定两个方法匹配(因为
Cat
参数)
- 因为前面提到的规则,Java只取最具体的一个(它不再关心参数是
Cat
这一事实)。
鉴于这种情况:
public class Animal {
public <T> void genericMethod(T t){
System.out.println("Inside generic method on animal with parameter " + t.toString());
}
}
public class Cat extends Animal {
public <T extends Cat> void genericMethod(T t){
System.out.println("Inside generic method on cat with parameter " + t.toString());
}
}
public class Main {
public static void main(String[] args) {
Animal animal = new Animal();
Cat cat = new Cat();
cat.genericMethod(cat);
}
}
class Cat
中的方法 genericMethod()
绝对不会覆盖 superclass 方法(如果我添加 @Override
签名,编译器会报错)这是合理的,因为对类型 T
的要求不同。
但是我不太明白,编译器是如何决定在main方法中调用cat.genericMethod(cat)
这两个方法中的哪一个。因为实际上这两种方法都是可见的,都是适用的。我本以为会出现像 "ambigous function call" 这样的编译器错误。有人可以解释这种行为吗?
由于子class方法的通用类型绑定,这两个方法具有不同的擦除。
对于超级 class 方法,擦除是:
public void genericMethod(Object t)
对于子 class 方法,擦除是:
public void genericMethod(Cat t)
方法重载解析规则选择参数最匹配的方法。因此,当您传递 Cat
参数时,会选择第二种 (sub-class) 方法。
Java,在编译时,会选择most specific matching method。
在您的示例中,这意味着该方法的 Cat
实现。
有两点需要注意:
- 如果你传递给它一个
Animal
,很明显只会使用在Animal中声明的方法(因为它不符合T extends Cat
约束)。 如果你传递给它
Cat
:- Java 决定两个方法匹配(因为
Cat
参数) - 因为前面提到的规则,Java只取最具体的一个(它不再关心参数是
Cat
这一事实)。
- Java 决定两个方法匹配(因为