有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

将JAXB、泛型和反射结合到XML中可以序列化所有Java类

我的代码如下:

    System.out.println("This will save a table to XML data sheet.");
    System.out.println("Please pick a table to save: " + listOfTables.toString());
    command = scan.nextLine();
    if(listOfTables.contains(command))
    {
        System.out.println("successfuly found table to save: " + command);
        try  //Java reflection
        {
            Class<?> myClass = Class.forName(command); // get the class named after their input
            Method listMethod = myClass.getDeclaredMethod("list"); // get the list method from the class
            Object returnType = listMethod.invoke(myClass, new Object[]{}); // run the list method
            ArrayList<Object> objectList = (ArrayList)returnType; // get the arraylist of objects to send to XML
            try 
            {
                JAXBContext jaxbContext = JAXBContext.newInstance(myClass);
                Marshaller marshaller = jaxbContext.createMarshaller();
                marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
                JAXBElement<?> jaxbElement = new JAXBElement<?>(new QName("jaxbdemo", "generated"), myClass, objectList.get(0));
                marshaller.marshal(jaxbElement, System.out);

            } catch (JAXBException e) {}
        }
        catch (ClassNotFoundException | SecurityException | NoSuchMethodException | IllegalAccessException | IllegalArgumentException | InvocationTargetException e) { }

我的问题是两者都不是:

JAXBElement<?> jaxbElement = new JAXBElement<?>(new QName("jaxbdemo", "generated"), myClass, objectList.get(0));

也不是:

JAXBElement<myClass> jaxbElement = new JAXBElement<myClass>(new QName("jaxbdemo", "generated"), myClass, objectList.get(0));

将编译。那么,我需要在<>;我的JAXBElement类型?顺便说一句,我得到:

The constructor JAXBElement<myClass>(QName, Class<myClass>, myClass) refers to the missing type myClass

以及:

Cannot instantiate the type JAXBElement<?>

共 (1) 个答案

  1. # 1 楼答案

    您需要使用助手方法来完成此操作。下面是一个粗略的例子:

    static <T> void helper(Class<T> myClass) {
    
        Method listMethod = myClass.getDeclaredMethod("list");
        Object returnType = listMethod.invoke(myClass, new Object[]{});
        @SuppressWarnings("unchecked") // [carefully document why this is okay here]
        ArrayList<T> objectList = (ArrayList<T>)returnType;
    
        ...
    
        JAXBElement<T> jaxbElement = new JAXBElement<T>(
                new QName("jaxbdemo", "generated"),
                myClass,
                objectList.get(0)
        );
    
        ...
    }
    

    从那时起,您可以自由地返回一个JAXBElement<?>,或者在助手中完成剩余的工作

    如前所述,您应该记录未经检查的强制转换,并解释为什么对由Class<T>表示的给定类调用list会保证返回ArrayList<T>,正如您的代码所假设的那样。这种方法在我看来最脆弱,当你调用^{}时,我已经发现了一个错误:

    listMethod.invoke(myClass, new Object[]{});
    

    该方法将调用该方法的实例作为其第一个参数(如果它是静态方法,则为null),但您正在传递myClass,这不可能是正确的