转换为在运行时确定的类

时间:2008-12-19 13:20:01

标签: java generics reflection casting reification

我有一个方法fetchObjects(String),预计会返回一个Contract业务对象数组。 className参数告诉我应该返回哪种业务对象(当然这在这个解释的案例中没有意义,因为我已经说过我会返回Contract s,但基本上就是我的情况在我的真实场景中)。所以我从某处获取了一组条目并加载了集合条目的类(其类型由className指定)。

现在我需要构造要返回的数组,因此我使用Set的{​​{1}}方法。使用反射,我构建了一个空的Contracts数组。 但是,这给了我一个静态类型toArray(T[])的值!接下来我需要将它转换为适当的类型,在本例中为Object(参见下面列表中的“带星号 - 下划线”部分)。

我的问题是:是否有一种方法,以及如何像我在列表中那样转换为Contract[] ,但只能通过来确定数组元素的类型(Contract[]Contract (或className)?换句话说,我想要做的事情基本上是这样的:entriesType,其中entriesType被通过(entriesType[]) valueWithStaticTypeObject参数指定的类替换,即classname

这在某种程度上是不可能的,还是可以以某种方式完成?也许使用泛型?

Contract

感谢。

<小时/> 更新:使用取自CodeIdol的类型安全方法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<Contract>(); return null; // Error } } ,我更新了toArray方法:

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<capture#3-of ?>, Class<capture#4-of ?>)" } public static <T> T[] toArray(Collection<T> c, Class<T> k) { T[] a = (T[]) java.lang.reflect.Array.newInstance(k, c.size()); int i = 0; for (T x : c) a[i++] = x; return a; } 方法的返回类型中指定Set<Contract>以便这可以工作?谢谢你的任何指示。

2 个答案:

答案 0 :(得分:7)

您可以使用该类作为参数,而不是类名。

   static <T extends Contract> T[] buildArray(Class<T> clazz){
     ArrayList<T> l=new ArrayList<T>();
     return l.toArray((T[]) java.lang.reflect.Array.newInstance(clazz, l.size()));
   }
编辑:(读杨评论后)

不,您不能将泛型类型与变量的值一起使用。

答案 1 :(得分:1)

那么为什么不使用

static <T> T[] buildArray(Class<T> clazz){
ArrayList<T> l=new ArrayList<T>();
return l.toArray((T[]) java.lang.reflect.Array.newInstance(clazz, l.size()));
}

请注意。修改了上面的代码。