Java泛型删除方法参数 [英] Java generics type erasure of method parameters

查看:106
本文介绍了Java泛型删除方法参数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

  public class Glommer< T> {
String glom(Collection<> obj){
String result =;
for(Object o:obj){
result + = o;
}
返回结果;
}

int glom(List< Integer> ints){
int result = 0;
for(int i:ints){
result + = i;
}
返回结果;
}

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()作为新Glommer< Integer>()。glom(字符串)不应该调用 int glom(List< Integer> int)方法,因为由于类型擦除,此方法实际上是 int glom(List ints)字符串的类型为 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);
}

}

结果是:

 对象方法



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


I got this one from a google I/O puzzler talk given by Joshua Bloch. Here's the code

 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));
      }

this main method throws an exception because new Glommer is a raw type and hence all the generics in Glommer is erased, so it ends up calling int glom(List<Integer> ints) rather than String glom(Collection<?> obj).

My question is, even if I called glom() as new Glommer<Integer>().glom(strings) shouldn't it call the int glom(List<Integer> ints) method since due to type erasure, this method is effectively int glom(List ints) and strings is of type List not Collection?

解决方案

The called method is defined at compilation time, not at runtime.

If you add a parameter to your constructor call, the compiler will have enough information to know that it has to call the first method. Otherwise, it's just as if generics didn't exist. In both case, the called method will always stay the same at runtime.

EDIT Some people seem to doubt, so here's another example:

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);
    }

}

The result is:

Object method

You pass an Integer to your method, but all that the compiler knows at compile time is that it's an object. The jvm doesn't automagically change the method call even though the Object is actually an Integer.

这篇关于Java泛型删除方法参数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆