Java - 创建扩展List的对象

时间:2014-01-06 18:03:25

标签: java list generics casting constructor

如何创建具有指定类型参数的列表? 例如:

LinkedList<Integer> list = createList(LinkedList.class, Integer.class);

我尝试为它创建一个方法,但该方法在创建新实例时不包含type参数。

public static <T, L extends List<T>> L createList(Class<L> listClazz, Class<T> valueClazz) throws Exception
{
    return listClazz.getConstructor().newInstance();

    //Instead of
    //  new L<T>();
    //does
    //  new L();
}

我希望我的问题很清楚,谢谢你的帮助。

2 个答案:

答案 0 :(得分:8)

你做不到。泛型在运行时没有业务,因此您无法使用反射在运行时创建参数化实例。在运行时,LinkedList<Intege>只是LinkedList。类型信息 - Integer在编译时通过“类型擦除”被擦除。关键是,你为什么要这样做?

答案 1 :(得分:1)

//Instead of
//  new L<T>();
//does
//  new L();

两个“做”完全相同的事情。你怎么知道它“做”而不是另一个?类型参数是用于类型检查的编译时幻象。它们与代码“做”无关。要创建LinkedList<T>的实例,您不需要知道T是什么,因为它在类型擦除后并不存在。

我认为你遇到的问题与函数内部的代码无关,而是与方法的签名有关。事实上,该方法是按原样声明的,并且您要向其传递Class<LinkedList>类型的表达式(LinkedList.class的类型),L必须为LinkedList由于该方法返回L,编译器必须考虑返回类型LinkedList。这些都与方法中的代码无关。

如果希望将方法的返回类型视为LinkedList<Integer>,则只需传入类型为Class<LinkedList<Integer>>的表达式。简单吧?你如何得到Class<LinkedList<Integer>>类型的表达式?例如,您可以(Class<LinkedList<Integer>>)(Class<?>)LinkedList.class

如果这看起来有些虚假,那是因为Class基本上是运行时的东西 - 它允许从该类运行时创建对象。将它与Generics(编译时类型检查机制)一起使用从根本上是有缺陷的。任何类都只有一个类对象,例如LinkedList。是LinkedList还是LinkedList<Integer>还是LinkedList<String>?好吧,它可能就是所有这些,在某种意义上,newInstance()方法可以创建它们中的任何一个(在运行时没有区别)。