泛型方法不覆盖超类中的类似泛型方法 -> 使用哪个?

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:

    1. Java 决定两个方法匹配(因为 Cat 参数)
    2. 因为前面提到的规则,Java只取最具体的一个(它不再关心参数是Cat这一事实)。