Java泛型在类型擦除后命名冲突

pat*_*fox 3 java generics

我正在阅读"Java Generics and Collections"一书,并且遇到了这段代码,它应该编译并运行而不会出错

class Overloaded {
    public static Integer sum(List<Integer> ints) {
        int sum = 0;
        for (int i : ints) sum += i;
        return sum;
    }
    public static String sum(List<String> strings) {
        StringBuffer sum = new StringBuffer();
        for (String s : strings) sum.append(s);
        return sum.toString();
    }
}
Run Code Online (Sandbox Code Playgroud)

但是,此示例无法编译时出错

错误:(16,26)java:name clash:sum(java.util.List)和sum(java.util.List)具有相同的擦除

我能理解为什么这是一个错误.但是,本书特别提到这是允许的,因为编译器可以根据返回类型区分这两种方法.

然后我在Java中找到了这个线程 Type Erasure and Overloading:为什么这样做?

它还建议这个例子应该编译.知道什么导致编译失败?

我使用的是JDK 1.8.这最近是用Java 1.8改变的吗?如果这是相关的,我使用最新的IntelliJ IDEA作为IDE.

che*_*ohi 5

我们知道,在运行时,Java擦除泛型类型,因此:

Integer sum(List<Integer> ints)
String sum(List<String> strings)
Run Code Online (Sandbox Code Playgroud)

将在运行时转换为:

Integer sum(List ints)
String sum(List strings)
Run Code Online (Sandbox Code Playgroud)

所以应该抛出这个编译器错误.

它编译时没有在JDK6中抛出错误,这是一个错误.这个bug已在JDK7中修复,因此使用JDK8编译会抛出此编译错误.

参考:

通用类在Java 6中编译,但不在Java 7中编译

  • 实际上,类型信息仍然存在于运行时,你甚至可以用反射来获取它:`ParameterizedType pType =(ParameterizedType)Overloaded.class.getMethod("sum",List.class).getGenericParameterTypes()[0];`它是就是这样,如果你用一个原始`List`调用`sum`,编译器就不知道要绑定哪个方法.调用者将被迫使用泛型来使调用不模糊,但这使得使用原始类型失败了. (3认同)