强制转换为在运行时确定的类 [英] Casting to a Class which is determined at run-time

查看:126
本文介绍了强制转换为在运行时确定的类的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个方法 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 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.

这篇关于强制转换为在运行时确定的类的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆