【问题标题】:Java Create Generic Arraylist by ReflectionJava 通过反射创建通用数组列表
【发布时间】:2014-06-19 05:32:34
【问题描述】:

我正在编写需要在 c# 和 java 上工作的对象序列化器/反序列化器类。我在下面的 c# 部分处理了这个问题:

Type listType = typeof(List<>);
                Type constructedListType;

                        type = item.Attributes["Type"].Value;
                        field = item.Attributes["Field"].Value;

                        if ((type == "Int32") || (type == "Int64") || (type == "Int16") || (type == "UInt32") || (type == "UInt64") || (type == "UInt16") || (type == "String") || (type == "Datetime") || (type == "Double") || (type == "Single"))
                        {
                            constructedListType = listType.MakeGenericType(Type.GetType(String.Format("{0}.{1}", "System", type)));
                        }
                        else
                        {
                            constructedListType = listType.MakeGenericType(Type.GetType(String.Format("{0}.{1}", WorkingNamespace, type)));
                        }

                        IList instance = (IList)Activator.CreateInstance(constructedListType);  

但是我在 Java 生成泛型数组列表时遇到了一个问题,该数组列表的对象类型来自 xml。

**已编辑

    type = attrMap.getNamedItem("Type").getNodeValue();
        field = attrMap.getNamedItem("Field").getNodeValue();
        type = reverseTypeConvert(type);
        Object oList;
        if ((type.equals("Integer") || type.equals("Long") || type.equals("Float") || type.equals("Short") || type.equals("String") || type.equals("Double") || type.equals("Date"))) {


            oList = Class.forName(String.format("java.util.ArrayList<%s.%s>","java.util",type)).newInstance();                  
        }
        else {

            oList = Class.forName(String.format("java.util.ArrayList<%s.%s>",this.workingPackage,type)).getGenericSuperclass();
        }

        if (!field.equals("none")) {
            Method setMethod = cObj.getClass().getMethod(String.format("%s%s", "set",field), oList.getClass());
            setMethod.invoke(cObj, oList);                  
        }

        deSerializeObject(node.getChildNodes(),oList);

所以,我在 Java 中找不到对应的 c# 代码。 感谢您的帮助!

好的,我们处理这个问题,我理解我的错误。 非常感谢。

【问题讨论】:

  • 能贴出你试过的java代码吗?
  • 为什么需要在运行时这样做?运行时的泛型真的不重要
  • 我编辑了@Hirak 的问题。
  • 请阅读 Java 中的 type erasure
  • 因为我需要转换列表的每个元素而不是只转换数组列表。此外,我正在编写通信协议,因此,序列化和反序列化需要在运行时进行。你有什么建议吗? @maress

标签: c# java generics reflection arraylist


【解决方案1】:

您尝试做的事情在 Java 中根本行不通。实际上,这比您尝试做的事情要容易得多(在某些方面)。由于@ElliottFrisch 指出的type erasure,在运行时,您消除了泛型类型。泛型仅由编译器使用,以确保您不会将对象添加到 List,例如,您不希望这样做。在运行时:

List<String> strings = new ArrayList<String>();

变成

List strings = new ArrayList();

因为编译器在编译它时就知道它,所以你可以放心,除非你用反射或类似的东西做一些疯狂的事情,否则列表中的每个对象都将是一个StringArrayList&lt;String&gt; 没有类,只有 ArrayList。泛型集合仅在 Objects 上运行,编译器在必要时提供转换。

TL;DR:泛型仅在编译时为您提供帮助。因为您使用反射来反序列化对象,所以无论如何您都不会这样做(实际上,类型安全也是一个编译时构造,您可以尝试在任何对象上调用任何方法,它就赢了除非它被实施,否则它不起作用)。您的代码将负责创建将添加到通用容器中的对象,并确保所有对象都是预期的类型。

【讨论】:

    【解决方案2】:

    Java 中的泛型只是一个编译时技巧。反射是运行时现象。因此,当您尝试使用反射创建列表时,无需使用泛型。只需创建一个原始类型的列表。它将接受对象。

    List oList = (List)Class.forName("java.util.ArrayList").newInstance();  
    

    或者可能是这样的?

    List oList;
            if ((type.equals("Integer") || type.equals("Long") || type.equals("Float") || type.equals("Short") || type.equals("String") || type.equals("Double") || type.equals("Date"))) {
    
    
                oList = new ArrayList<Number>();                  
            }
            else {
    
                oList = new ArrayList<Object>();
            }
    

    【讨论】:

    • 有没有办法做到这一点? oList = new ArrayList(); TYPE是来自xml的字符串
    猜你喜欢
    • 2013-05-11
    • 1970-01-01
    • 2012-02-25
    • 2011-03-02
    • 2022-12-07
    • 1970-01-01
    • 1970-01-01
    • 2011-01-13
    • 1970-01-01
    相关资源
    最近更新 更多