Java泛型类型擦除方法参数

时间:2012-12-20 16:56:56

标签: java generics types

我从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

3 个答案:

答案 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)方法。

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