XML序列化和空构造函数

时间:2013-05-13 22:10:32

标签: java serialization xml-serialization

我有以下类允许我在程序中序列化对象:

import java.beans.XMLDecoder;
import java.beans.XMLEncoder;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;

public class Persistor<T> {

    private T data;

    public void save(T data, String file) {

        try {

            FileOutputStream os = new FileOutputStream(file);
            XMLEncoder encoder = new XMLEncoder(os);
            encoder.writeObject(data);
            encoder.close();

        } catch(FileNotFoundException e) {

            System.out.println("File not found");

        }

    }

    @SuppressWarnings({ "unchecked", "finally" })
    public T read(String file) {

        try {

            FileInputStream fis = new FileInputStream(file);
            XMLDecoder decoder = new XMLDecoder(fis);
            data = (T)decoder.readObject();
            decoder.close();

        } catch(FileNotFoundException e) {

            System.out.println("File not found");

        } finally {

            return data;

        }

    }

}

问题是我有我的业务逻辑包,其中包含类似学生的类,似乎我需要一个空的构造函数public Student() {}来使程序正常工作:

package logic;

public class Student {

    private String name;

    public Student(String name) {

        this.name = name;

    } public Student() {} // empty constructor

    public String getName() {

        return name;

    }

    public void setName(String name) {

        this.name = name;

    }

    public String toString() {

        return name;

    }

}

如果我取出空构造函数,控制台上会出现以下异常:

java.lang.InstantiationException: logic.Student
Continuing ...
java.lang.IllegalStateException: The outer element does not return value
Continuing ...

有没有办法解决这个问题,我的意思是没有空构造函数?因为我还有7个类,每个人都需要拥有它自己的空构造函数。

2 个答案:

答案 0 :(得分:1)

您可以尝试ConstructorProperties注释

public class Student {
    private String name;

    @ConstructorProperties("name")
    public Student(String name) {
        this.name = name;
    } 

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

测试

public class Test1 {

    public static void main(String[] args) throws Exception {
         Student s1 = new Student("Jon");
         XMLEncoder encoder = new XMLEncoder(new FileOutputStream("xxx"));
         encoder.writeObject(s1);
         encoder.close();

         XMLDecoder decoder = new XMLDecoder(new FileInputStream("xxx"));
         Student s2 = (Student)decoder.readObject();
         decoder.close();
         System.out.println(s2);
    }
}

输出

test.Student@e3fd79

答案 1 :(得分:0)

您正在尝试反序列化bean。 包括XMLEncoder / Decoder在内的大多数序列化框架的实现方式是实例化一个默认的无参数构造函数,然后反复调用每个成员对象的getter或setter。

文档似乎支持这个......

XMLDecoder javadoc

  

XMLDecoder类用于读取使用XML创建的XML文档   XMLEncoder和就像ObjectInputStream一样使用。

ObjectInputStream javadoc

  

读取对象类似于运行new的构造函数   宾语。为对象分配内存并初始化为零   (空值)。为非序列化调用no-arg构造函数   类,然后恢复可序列化类的字段   从最接近的可序列化类开始的流   java.lang.object并使用对象最具体的类完成。

     

...

     

序列化不会读取或为任何字段赋值   没有实现java.io.Serializable接口的对象。   不可序列化的对象的子类可以是可序列化的。   在这种情况下,非可序列化类必须具有无参数构造函数   允许其字段初始化。在这种情况下,它是   子类的责任是保存和恢复状态   不可序列化的类。经常是这样的领域   该类可访问(公共,包或受保护)或那些   有get和set方法可用于恢复状态。

从文档中可以看出,您的选项要么是实现Serializable,要么添加no-arg构造函数,并为所有字段保留getter和setter。