如何将泛型类传递给Java中的方法?

时间:2011-04-16 00:12:43

标签: java generics dynamic methods arguments

假设我们有一个函数可以创建给定特定类的对象:

public static <T> T createObject(Class<T> generic) {
    try {
        return generic.newInstance();
    } catch (Exception ex) {
        return null;
    }
}

我们可以轻松地使用该函数来创建非泛型类型的实例。

public static void main(String[] args) {
    Foo x = createObject(Foo.class);
}

是否可以使用泛型类型执行相同的操作?

public static void main(String[] args) {
    ArrayList<Foo> x = createObject(ArrayList<Foo>.class); // compiler error
}

3 个答案:

答案 0 :(得分:8)

Java中的泛型是通过类型擦除实现的。

这意味着ArrayList<T>在运行时是ArrayList。编译器只是为您插入强制转换。

您可以使用以下方法对此进行测试:

ArrayList<Integer> first = new ArrayList<Integer>();
ArrayList<Float> second = new ArrayList<Float>();

if(first.getClass() == second.getClass())
{
    // should step in the if
}

答案 1 :(得分:1)

此外,只要您确定自己在做什么,并且只要您确信您的代码不会产生堆污染,您就可以取消警告。

您可能还会考虑到您的代码无法实例化数组,这很可能也需要一个未经检查的异常:

@SuppressWarnings("unchecked")
public static <T> T[] createArray(Class<T> anyClass, int size){
    T[]result = null;
    try{
        result = (T[]) Array.newInstance(anyClass, size);
    }catch(Exception e){
        e.printStackTrace();
    }
    return result;
}

这就是我使用它的方式:

public static void main(String[] args) throws Exception{
    @SuppressWarnings("unchecked")
    List<String> jediNames = (List<String>) createObject(ArrayList.class);
    jediNames.add("Obiwan");

    String[] moreJedis = createArray(String.class, 10);
    System.out.println(moreJedis.length);
    moreJedis[0] = "Anakin";
}

答案 2 :(得分:0)

如果你真的需要,你可以强制它编译而不会出现错误或警告:

@SuppressWarnings("unchecked")
ArrayList<Foo> x = (ArrayList<Foo>) createObject(ArrayList.class);

唯一的麻烦是,在编译时,它无法保证createObject()不会向ArrayList添加非{1}类型的对象。在您的情况下,这可能是安全的,因此您仍然可以获得仿制药的好处而无需使用Foo