强制转换为在运行时确定的类 [英] Casting to a Class which is determined at run-time
问题描述
我有一个方法 fetchObjects(String)
,希望返回一个 Contract
数组。 className
参数告诉我应该返回什么样的业务对象(当然这在本案例中没有意义,因为我已经说过我会返回 Contract
s,但它基本上是我在我的实际情况下的情况)。所以我从某处获取一组条目,并加载集合条目(类型由 className
指定)的类。
现在我需要构造数组来返回,所以我使用 Set
's toArray(T [])
方法。使用反射,我自己构建一个空的合同数组。 但是,这给了我一个静态类型 Object
的值!所以接下来我需要把它转换为适当的类型,在这种情况下是 Contract []
(参见下面的列表中的星号下划线部分)。
我的问题是:有没有办法,如何投资到 Contract []
c> (或 )确定数组元素的类型(
)?换句话说,我想做的是基本上像这样投入: Contract
code> entriesType (entriesType [])valueWithStaticTypeObject
,其中entriesType由通过<$ cc $ c> 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 =http://codeidol.com/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 Contract
s, 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.
这篇关于强制转换为在运行时确定的类的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!