转换为在运行时确定的类
我有一个方法fetchObjects(String)
,期望返回一个Contract
业务对象数组。 className
参数告诉我应该返回什么样的业务对象(当然这在这个解释的情况下没有意义,因为我已经说过我将返回Contract
s,但它基本上是我在实际场景中的情况)。 所以我从某处获取了一组条目并加载了集合条目的类(其类型由className
指定)。
现在我需要构造要返回的数组,所以我使用Set
的toArray(T[])
方法。 使用reflection,我构建了一个空的Contracts数组。 但是,这给了我静态类型Object
的值! 接下来我需要将它转换为适当的类型,在本例中是Contract[]
(参见下面列表中的“带星号 – 下划线”部分)。
我的问题是:有没有办法,如何,如同在列表中那样转换为Contract[]
, 但只通过className
(或entriesType
) 确定数组元素的类型( Contract
)? 换句话说,我想做的基本上是这样的: (entriesType[]) valueWithStaticTypeObject
,其中entriesType被classname
参数指定的classname
替换,即Contract
。
这在某种程度上是不可能的,还是可以以某种方式完成? 也许使用generics?
package xx.testcode; import java.util.HashSet; import java.util.Set; class TypedArrayReflection { public static void main(String[] args) { try { Contract[] contracts = fetchObjects("Contract"); System.out.println(contracts.length); } catch (ClassNotFoundException e) {} } static Contract[] fetchObjects(String className) throws ClassNotFoundException { Class entriesType = Class.forName("xx.testcode."+className); Set entries = ObjectManager.getEntrySet(className); return entries.toArray( (Contract[]) java.lang.reflect.Array.newInstance( /********/ entriesType, entries.size()) ); } } class Contract { } // business object class ObjectManager { static Set getEntrySet(String className) { if (className.equals("Contract")) return new HashSet(); return null; // Error } }
谢谢。
更新:使用类型安全方法toArray
,取自fetchObjects
,我更新了我的fetchObjects
方法:
static Contract[] fetchObjects(String className) throws ClassNotFoundException { Class entriesType = Class.forName("xx.testcode."+className); Set entries = ObjectManager.getEntrySet(className); return toArray(entries, entriesType); // compile error // -> "method not applicable for (Set, Class)" } public static T[] toArray(Collection c, Class k) { T[] a = (T[]) java.lang.reflect.Array.newInstance(k, c.size()); int i = 0; for (T x : c) a[i++] = x; return a; }
我需要做些什么才能摆脱评论中引用的编译器错误? 我是否必须在getEntrySet
方法的返回类型中指定Set
以便这可以工作? 谢谢你的任何指示。
您可以使用该类作为参数,而不是类名。
static T[] buildArray(Class clazz){ ArrayList l=new ArrayList (); return l.toArray((T[]) java.lang.reflect.Array.newInstance(clazz, l.size())); }
编辑:(读杨评论后)
不,您不能将generics类型与变量的值一起使用。
那么为什么不用
static T[] buildArray(Class clazz){ ArrayList l=new ArrayList (); return l.toArray((T[]) java.lang.reflect.Array.newInstance(clazz, l.size())); }
注意。 修改了上面的代码。