5

list.toArray(T[] a),如果T是“运行时类型”怎么办?

ListJava中的“ ”接口,方法:T[] toArray(T[] a)
好的,这是一个很老的问题,通常我们这样使用它:

String[] array = list.toArray(new String[0]);
String[] array = list.toArray(new String[list.size()]);

我的问题是,我在编码时不知道“T”类型是什么,“T”类型只能在运行时决定,这里是例子:

List list=...;  // no generic type declared on this List
Class<?> clazz=...; //yeah, this is the real type of the element of the list, I can sure about that

现在我需要将列表转换为元素类型为clazz的数组,我该怎么办?

可能你想知道为什么我有这种需求:
我正在对 Morphia 进行一些修改(它是一个 java-mongoDB 框架)。我需要从 mongoDB 获取数据并将其设置到 POJO 的正确字段中。在某些情况下,字段类型是数组,获取的数据是一个BasicDBList实体(它扩展了ArrayList),所以必须将BasicDBList实体转换成一个与POJO字段类型兼容的数组。

我查看了 ArrayList 的源代码,然后用一些丑陋的代码实现了我的目标:

List list=...;
Class<?> clazz=...;
Object targetArray=Array.newInstance(clazz, list.size());
list.toArray((Object[])targetArray);

请问有没有更好的方法来做到这一点?

4

2 回答 2

5

如果您的类型仅在运行时已知,则此处没有解决方案。

Java 泛型是编译时检查,实际上并不存在于运行时,它被称为类型擦除http://docs.oracle.com/javase/tutorial/java/generics/erasure.html

这意味着运行时环境不进行此类检查(例如,您可以将 Integers 放入通常类型为 String 的 List 中,并且使用 Object o = list.get(0) 会运行得很好)

泛型的真正意义在于提供编译时检查以防止编码错误

于 2012-11-13T04:01:03.607 回答
1

在评论中@arne.b 的帮助下,我认为没有更好的方法可以做到这一点:

List list=...;
Class<?> clazz=...;
Object[] targetArray=(Object[])Array.newInstance(clazz, list.size());
Object[] myArray=list.toArray(targetArray);

然后我可以将其设置为字段而不会出错:

Field field=...;    //ComponentType of this field can be sure is "clazz"
field.set(entity,myArray);

或者我可以这样做以手动将其转换为实际类型:

Class<?> arrayClazz=Class.forName("[L"+clazz.getName()+";");
arrayClazz.cast(myArray);
于 2012-11-22T09:39:22.630 回答