关于Java:如何获取参数化的Class实例

关于Java:如何获取参数化的Class实例

How to get parametrized Class instance

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

我无法弄清楚的是如何获取本身已参数化的Class类型的实例,即Class >。 像下面的代码片段一样:

1
2
3
4
5
6
7
8
9
10
11
12
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);
    }
}

我经常遇到这个问题的变种,但我仍然不知道,是否只是想念一些东西,或者真的没有更好的方法。 感谢您的建议。


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

您无法使用.class表示法实例化它们的原因是,这是用于类文字的特殊语法。参数化类型时,Java语言规范特别禁止使用此语法,这就是为什么不允许List .class的原因。


我认为您无法做自己想做的事情。首先,您的实例化方法不知道它处理的是参数化类型(您可以轻松地将其传递给java.util.Date.class)。其次,由于擦除,在运行时对参数化类型进行特别特定的操作是困难的或不可能的。

如果您以不同的方式解决问题,则可以做其他一些小技巧,例如类型推断:

1
2
3
4
5
6
7
8
9
10
11
12
13
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();
    }
}


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


您唯一可以做的就是直接实例化List并调用其getClass()

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

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


推荐阅读