Javagenerics类型擦除方法参数

我从Joshua Bloch给出的谷歌I / O益智游戏中得到了这个。 这是代码

public class Glommer { String glom(Collection obj){ String result = ""; for(Object o : obj){ result += o; } return result; } int glom(List ints){ int result = 0; for(int i : ints){ result += i; } return result; } public static void main(String args[]){ List strings = Arrays.asList("1", "2", "3"); System.out.println(new Glommer().glom(strings)); } 

这个main方法抛出一个exception,因为new Glommer是一个原始类型,因此new Glommer中的所有genericsGlommer被擦除,所以它最终调用int glom(List ints)而不是String glom(Collection obj)

我的问题是,即使我将glom()称为new Glommer().glom(strings)也不应该调用int glom(List ints)方法,因为由于类型擦除,这种方法是有效的int glom(List ints)stringsList not Collection类型?

被调用的方法是在编译时定义的,而不是在运行时定义的。

如果向构造函数调用添加参数,编译器将有足够的信息知道它必须调用第一个方法。 否则,就好像仿制药不存在一样。 在这两种情况下,被调用的方法在运行时将始终保持不变。

编辑有些人似乎怀疑,所以这是另一个例子:

 public class Test { private static void test(Object object) { System.out.println("Object method"); } private static void test(Integer integer) { System.out.println("Integer method"); } public static void main(String[] args) { Object object = Integer.valueOf(0); test(object); } } 

结果是:

 Object method 

您将Integer传递给您的方法,但编译器在编译时知道的所有内容都是它是一个对象。 即使Object实际上是一个Integer,jvm也不会自动更改方法调用。

您可以阅读有关原始类型的更多信息以完全理解它

基本上,原始类型是用于使用遗留代码,原始类中的任何东西几乎都会变成原始的,在这种情况下就是那两种方法。

因此,当它是raw时,有一个方法可以获取List和一个Collection因此它被称为List one,如果它不是raw,那么方法也不是raw,它会调用Collection一个,因为它有额外的信息

这是因为当没有genericsGeneric()调用new Glommer()时,将从类中删除所有类型匹配。

由于strings变量是List ,如果它没有任何generics那么它将匹配glom(List ints) 。 类型检查直到稍后才完成。

当我们创建new Glommer ,类型都保留在原位,所以当我们传递我们的strings变量时,它会进行类型检查。 编译器现在可以检查它是否是List ,这不是因为它被传递给glom(Collection obj)方法。

希望这有帮助,如果您需要,请询问任何澄清!