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

时间:2018-02-08 07:43:22

标签: java generics ambiguous

鉴于这种情况:

 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);
    }
}

genericMethod()中的方法Cat绝对不会覆盖超类方法(并且编译器会抱怨,如果我添加@Override签名),这是合理的,作为对类型的要求{ {1}}不同。

但我不太明白,编译器如何决定在main方法的调用T中使用哪两种方法。因为实际上两种方法都是可见的并且都适用。我本来期望编译器错误,如“ambigous函数调用”。有人可以解释这种行为吗?

2 个答案:

答案 0 :(得分:7)

由于子类方法的泛型类型绑定,这两种方法具有不同的擦除。

对于超类方法,擦除是:

::value

对于子类方法,擦除是:

template

方法重载解析规则选择具有最佳匹配参数的方法。因此,当您传递public void genericMethod(Object t) 参数时,将选择第二个(子类)方法。

答案 1 :(得分:3)

Java在编译时将选择most specific matching method。 在您的示例中,这意味着方法的Cat实现。

这有两点需要注意:

  • 如果你传递给Animal,很明显只会使用在Animal中声明的方法(因为它与T extends Cat约束不匹配)。
  • 如果您传递给Cat

    1. Java决定两种方法匹配(因为Cat参数)
    2. 由于上述规则,Java只采用最具体的规则(它不再关心参数是Cat)。