9

由于引入了泛型,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

4 回答 4

8

Class 类是一种类型的运行时表示。由于参数化类型在运行时会进行类型擦除,因此 Class 的类对象将与 Class<List<Integer>> 和 Class<List<String>> 相同。

不能使用 .class 表示法实例化它们的原因是这是用于类文字的特殊语法。当类型被参数化时, Java 语言规范明确禁止这种语法,这就是不允许 List<String>.class 的原因。

于 2008-09-16T12:35:42.310 回答
1

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

于 2008-09-16T12:43:09.967 回答
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();
    }
}
于 2008-09-16T12:43:22.870 回答
0

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

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

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

于 2012-11-13T17:04:13.117 回答