如何获取参数化的Class实例

时间:2008-09-16 12:08:22

标签: java generics

由于引入了泛型,Class被参数化,因此List.class生成Class< List>。这很清楚。

我无法弄清楚的是如何获得一个自身参数化的类型的实例,即Class< List< String>>。就像在这个片段中一样:

public class GenTest {
    static <T> T instantiate(Class<T> clazz) throws Exception {
        return clazz.newInstance();
    }
    public static void main(String[] args) throws Exception {
        // Is there a way to avoid waring on the line below
        // without using  @SuppressWarnings("unchecked")?
        // ArrayList.class is Class<ArrayList>, but I would like to
        // pass in Class<ArrayList<String>>
        ArrayList<String> l = GenTest.instantiate(ArrayList.class);
    }
}

我经常遇到这个问题的变化,我仍然不知道,如果我错过了什么,或者是否真的没有更好的方法。谢谢你的建议。

4 个答案:

答案 0 :(得分:8)

Class类是类型的运行时表示。由于参数化类型在运行时经历类型擦除,因此Class的类对象将与Class&lt; List&lt; Integer&gt;&gt;相同。和类&lt; List&lt; String&gt;&gt;。

您无法使用.class表示法实例化它们的原因是这是用于类文字的特殊语法。当参数化类型时,Java Language Specification特别禁止使用此语法,这就是不允许使用List&lt; String&gt; .class的原因。

答案 1 :(得分:1)

类表示由类加载器加载的类,它们是原始类型。要表示参数化类型,请使用java.lang.reflect.ParameterizedType。

答案 2 :(得分:1)

我认为你不能做你想做的事。首先,你的实例化方法不知道它处理参数化类型(你可以很容易地传递它java.util.Date.class)。其次,由于擦除,在运行时使用参数化类型进行特别特定的操作很困难或不可能。

如果你以不同的方式解决问题,你可以做其他一些小动作,比如类型推理:

public class GenTest
{
    private static <E> List<E> createList()
    {
        return new ArrayList<E>();
    }

    public static void main(String[] args)
    {
        List<String> list = createList();
        List<Integer> list2 = createList();
    }
}

答案 3 :(得分:0)

您唯一能做的就是直接实例化List<String> 并调用其getClass()

instantiate(new List<String>() { ... }.getClass());

对于具有多个抽象方法(如List)的类型,这非常尴尬。但不幸的是,调用子类构造函数(如new ArrayList<String>)或工厂方法(Collections.<String>emptyList())不起作用。