2014-11-02 122 views
4

因此,Google提出了很多关于获取参数化类型.class的问题,但我试图以另一种方式。如何使用Class对象作为参数化类型?

我有一个类的列表,我需要制作一个地图,它使用Class作为键和一个类型为Class的对象的ArrayList作为值。就像这样:

Class[] classes = getArrayOfClasses(); 
HashMap<Class, ArrayList<?>> map = new HashMap<Class, ArrayList<?>>(); 
for(Class c : classes) { 
    map.put(c, new ArrayList<c>()); // here is where the problem is 
} 

问题当然是它需要一个参数化类型,而不是一个类。一种可能的解决方法是只使用map.put(c, new ArrayList<Object>()),但是我必须知道类型并投射每个物体。

MyClass myObj = (MyClass) map.get(MyClass.class).get(0); 

我也试图使一个初始化函数是这样的:

private <T> ArrayList<T> makeArrayList(Class<T> c) { 
    return new ArrayList<T>(); 
} 

这不得不说我希望将工作的语法,但它仍然给我留下的ObjectArrayList是不得不投。

那么有什么办法可以让ArrayList参数化为类的类型?

+0

使用通用方法:'列表 getList(类别类型)'。 – 2014-11-02 19:51:07

回答

2

不幸的是,由于Java泛型的性质(它们通过擦除工作),泛型在运行时不可用。

这意味着没有真正的方法来使map.put(c, new ArrayList<c>());工作。

我建议不要做这样的:裹在一个专门的对象列表,并给该对象的下列访问方法:

public <T> getList(Class<T> key) { 
    List<?> list = map.get(key); 
    return (List<T>) list; 
} 

这将产生一个警告,但只要在地图构建好吧,你会没事的。

或者,您可以对所有对象执行运行时检查,以确保类型匹配。

public <T> getList(Class<T> key) { 
    List<?> list = map.get(key); 
    for(Object o : list){ 
     assert(key.isInstance(o)); 
    } 
    return (List<T>) list; 
} 
+0

我希望有一种方式来解决类型擦除类型是一个类,但我猜不是。在一个函数中包装演员并抑制警告可能是最好的解决方法。谢谢 – 2014-11-02 21:14:35

1

是绝对在编译的字节代码之间没有差异:

new ArrayList(); 
new ArrayList<T>(); 
new ArrayList<String>(); 
new ArrayList<Integer>(); 

类型参数对经编译的代码没有影响;它只影响编译器的类型检查。所以,如果类型参数在编译时不可用,那么它是没用的,因为编译时是唯一有用的时间。

您应该只写new ArrayList<Object>()new ArrayList<Integer>()甚至new ArrayList<CompletelyBogusUnrelatedClass>();这并不重要,因为它们都与ArrayList<?>兼容,这是您的地图的值类型。

至于你的方法,创建并返回一个ArrayList,它应该只是这样写:

private static <T> ArrayList<T> makeArrayList() { 
    return new ArrayList<T>(); 
} 

(这是正确的,这个方法返回的任何元素类型你想要ArrayList甚至不知道什么这种类型是!这是一个清楚的演示,在运行时不需要类型参数。)

相关问题