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)
和strings
是List
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)
方法。
希望这有帮助,如果您需要,请询问任何澄清!