覆盖方法中的泛型

Kie*_*old 14 java generics overloading

进入一个有趣的问题; 以下类编译:

public class Test {

    public static void main(String[] args) throws Exception {
        A a = new A();
        B b = new B();

        foo(a);
        foo(b);
    }   

    private static void foo(A a) {
        System.out.println("In A");
    }   

    private static void foo(B b) {
        System.out.println("In B");
    }   

    private static class A {}

    private static class B extends A {}

}
Run Code Online (Sandbox Code Playgroud)

但是这个失败了:

public class Test {

    public static void main(String[] args) throws Exception {
        A<String> a = new A<>();
        B b = new B();

        foo(a);
        foo(b);
    }   

    private static void foo(A<String> a) {
        System.out.println("In A");
    }   

    private static void foo(B b) {
        System.out.println("In B");
    }   

    private static class A<T> {}

    private static class B extends A {}

}
Run Code Online (Sandbox Code Playgroud)

有这个错误:

Test.java:8: error: reference to foo is ambiguous, both method foo(A<String>) in Test and method foo(B) in Test match              
        foo(b);                                                                                                                    
        ^                                                                                                                          
Note: Test.java uses unchecked or unsafe operations.                                                                               
Note: Recompile with -Xlint:unchecked for details.                                                                                 
1 error
Run Code Online (Sandbox Code Playgroud)

我认为由于类型擦除,这些基本相同.谁知道这里发生了什么?

Zho*_*gYu 2

在泛型出现之前,Java 有类似的方法

\n\n
public class Collections\n\n    public void sort(List list) {...}               [1]\n
Run Code Online (Sandbox Code Playgroud)\n\n

用户代码可能有类似的内容

\n\n
public class MyList implements List ...             [2]\n\nMyList myList = ...;\nCollections.sort(myList);                           [3]\n
Run Code Online (Sandbox Code Playgroud)\n\n

当泛型被添加到 Java 中时,我们决定将现有的类和方法转换为泛型类和方法,而不会破坏使用它们的任何代码。就难度而言,这是一项伟大的成就,但代价是使语言变得复杂且存在缺陷。

\n\n

所以[1]被泛化了,但[3]仍然必须按原样编译,而不必泛化[2]

\n\n

黑客攻击位于\xc2\xa715.12.2.3

\n\n
\n

ai可以通过方法调用转换(\xc2\xa75.3)转换为Si

\n
\n\n

基本上是说,如果参数类型 (Ai) 是原始类型,则也删除参数类型 (Si) 以进行匹配。

\n\n

回到您的示例,我们了解为什么foo(A<String>)被认为适用于foo(b).

\n\n

然而还有另一个问题 - 是否foo(A<String>)适用于 [\xc2\xa715.12.2.2]?从规范的字面来看,答案似乎是“不”。但这可能是规范的错误。

\n