我从Joshua Bloch给出的谷歌I / O益智游戏中得到了这个。这是代码
public class Glommer<T> {
String glom(Collection<?> obj){
String result = "";
for(Object o : obj){
result += o;
}
return result;
}
int glom(List<Integer> ints){
int result = 0;
for(int i : ints){
result += i;
}
return result;
}
public static void main(String args[]){
List<String> strings = Arrays.asList("1", "2", "3");
System.out.println(new Glommer().glom(strings));
}
此主方法抛出异常,因为new Glommer
是原始类型,因此Glommer
中的所有泛型都被删除,因此最终调用int glom(List<Integer> ints)
而不是String glom(Collection<?> obj)
我的问题是,即使我将glom()
称为new Glommer<Integer>().glom(strings)
也不应该调用int glom(List<Integer> ints)
方法,因为由于类型擦除,此方法实际上是int glom(List ints)
并且strings
的类型为List
而不是Collection
?
答案 0 :(得分:7)
被调用的方法是在编译时定义的,而不是在运行时定义的。
如果在构造函数调用中添加参数,编译器将有足够的信息知道它必须调用第一个方法。否则,就好像仿制药不存在一样。在这两种情况下,被调用的方法在运行时始终保持不变。
编辑有些人似乎有疑问,所以这是另一个例子:
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也不会自动更改方法调用。
答案 1 :(得分:1)
您可以详细了解Raw Types以完全理解
基本上,原始类型用于使用遗留代码,原始类中的任何内容都将变为原始数据,在这种情况下是这两种方法。
因此,当它是raw时,有一个方法可以得到List
,一个用于Collection
,因此它被称为List
,如果它不是原始的,那么方法也不是原始的它会调用Collection
,因为它有额外的信息
答案 2 :(得分:0)
这是因为在new Glommer()
没有泛型的情况下调用Generic<Type>()
时,所有类型匹配都会从类中删除。
由于字符串变量是List
,如果它没有任何通用<Type>
,那么它将匹配glom(List ints)
。类型检查直到稍后才完成。
当我们创建new Glommer<AnyType>
时,所有类型都保留在原位,因此当我们传递strings
变量时,它会进行类型检查。编译器现在可以检查它是否是List<Integer>
,这不是因为它被传递给glom(Collection<?> obj)
方法。
希望这有帮助,如果您需要,请询问任何澄清!