我有一个方法 fetchObjects(String),希望返回一个 Contract 数组。 className 参数告诉我应该返回什么样的业务对象(当然这在本案例中没有意义,因为我已经说过我会返回 Contract s,但它基本上是我在我的实际情况下的情况)。所以我从某处获取一组条目,并加载集合条目(类型由 className 指定)的类。
现在我需要构造数组来返回,所以我使用 Set 's toArray(T [])方法。使用反射,我自己构建一个空的合同数组。 但是,这给了我一个静态类型 Object 的值!所以接下来我需要把它转换为适当的类型,在这种情况下是 Contract [] (参见下面的列表中的星号下划线部分)。
我的问题是:有没有办法,如何投资到 Contract [] c> (或 )确定数组元素的类型( Contract code> entriesType )?换句话说,我想做的是基本上像这样投入:(entriesType [])valueWithStaticTypeObject ,其中entriesType由通过 classname 参数,即 Contract 。
或者可以做一些什么?也许使用泛型?
package xx.testcode; import java.util.HashSet; import java.util.Set; class TypedArrayReflection { public static void main(String [] args){ try { Contract [] contracts = fetchObjects ); System.out.println(contracts.length); } catch(ClassNotFoundException e){} } static Contract [] fetchObjects(String className)throws ClassNotFoundException { Class& entriesType = Class.forName(xx.testcode。+ className); 设置<?> entries = ObjectManager.getEntrySet(className); return entries.toArray((Contract [])java.lang.reflect.Array.newInstance( / ******** / entriesType,entries.size()) ); } } class Contract {} //业务对象 class ObjectManager { static Set<?> getEntrySet(String className){ if(className.equals(Contract)) return new HashSet< Contract>(); return null; //错误} }$ b
更新:使用类型安全方法 toArray href =codeidol/java/javagenerics/Reification/The-Principle-of-Truth-in-Advertising/ =nofollow noreferrer> CodeIdol ,我更新了我的 fetchObjects 方法:
static Contract [] fetchObjects(String className)throws ClassNotFoundException { Class<?> entriesType = Class.forName(xx.testcode。+ className); 设置<?> entries = ObjectManager.getEntrySet(className); return toArray(entries,entriesType); // compile error // - > 方法不适用于(< 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; }我需要做什么来摆脱评论?我是否必须在我的 getEntrySet 方法的返回类型中指定 Set< Contract> 感谢任何指针。
解决方案您可以使用类作为参数,而不是类名。
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())); }(阅读Yang评论后)
否,不能将泛型类型与变量的值一起使用。
I have a method fetchObjects(String) that is expected to return an array of Contract business objects. The className parameter tells me what kind of business objects I should return (of course this doesn't make sense in this construed case because I already said I will return Contracts, but it's basically the situation I have in my real scenario). So I get the set of entries from somewhere and load the class of the collection's entries (the type of which is specified by className).
Now I need to construct the array to return, so I use Set's toArray(T[]) method. Using reflection, I build myself an empty Contracts array. But, this gives me a value of static type Object! So next I need to cast it to the appropriate type, which in this case is Contract[] (see "asterisk-underlined" part in the listing below).
My question is: Is there a way, and how, to cast to Contract[] as I do in the listing, but determining the type of the array elements (Contract) only through className (or entriesType)? In other words, what I'd like to do is basically casting like this: (entriesType[]) valueWithStaticTypeObject, where entriesType be replaced by the class specified through the classname parameter, i.e. Contract.
Is this somehow inherently impossible, or can it be done somehow? Maybe using 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<Contract>(); return null; // Error } }Thanks.
Update: Using the type-safe method toArray, taken from CodeIdol, I updated my fetchObjects method thus:
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; }What do I need to do to get rid of the compiler error quoted in the comment? Do I absolutely have to specify Set<Contract> in the return type of my getEntrySet method so that this can work? Thanks for any pointers.
解决方案You may use the class as the parameter rather then the class name.
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())); }EDIT: (after read Yang comment)
No, You cannot use generic type with the value of a variable.
更多推荐
强制转换为在运行时确定的类
发布评论