代码之家  ›  专栏  ›  技术社区  ›  Yang Meyer

强制转换到运行时确定的类

  •  5
  • Yang Meyer  · 技术社区  · 17 年前

    我有一个方法 fetchObjects(String) 它将返回 Contract 业务对象。这个 className 参数告诉我应该返回什么类型的业务对象(当然,在这种情况下这是不合理的,因为我已经说过要返回 合同 但这基本上是我真实场景中的情况)。因此,我从某处获取一组条目,并加载集合条目的类(其类型由 类名 )

    现在我需要构造要返回的数组,所以我使用 Set 的 toArray(T[]) 方法。使用反射,我为自己构建了一个空的契约数组。 但是, 这给了我一个静态类型的值 Object !接下来我需要将其转换为适当的类型,在本例中是 Contract[] (见下表中的“带下划线的星号”部分)。

    我的问题是:有没有一种方法,以及如何 合同[ ] 正如我在清单中所做的, 但是确定数组元素的类型( 合同 只有通过 类名 (或) entriesType )?换句话说,我想做的基本上是这样的演员: (entriesType[]) valueWithStaticTypeObject ,其中EntriesType将替换为通过 classname 参数,即 合同 .

    这在某种程度上是不可能的,还是可以通过某种方式实现?可能使用仿制药?

    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 ,取自 CodeIdol 我更新了我的 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> 在我的返回类型中 getEntrySet 方法,以便这可以工作?谢谢你的指点。

    2 回复  |  直到 17 年前
        1
  •  7
  •   Dennis C    17 年前

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

       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()));
       }
    

    编辑:(阅读杨评论后)

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

        2
  •  1
  •   Milhous    17 年前

    所以为什么不使用

    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()));
    }
    

    注意事项。从上面修改了代码。