1

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

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 个类,每个人都需要有自己的空构造函数。

4

2 回答 2

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
于 2013-05-13T22:33:53.920 回答
0

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

文档似乎支持这一点......

XMLDecoder javadoc

XMLDecoder 类用于读取使用 XMLEncoder 创建的 XML 文档,其使用方式与 ObjectInputStream 类似。

对象输入流 javadoc :

读取对象类似于运行新对象的构造函数。为对象分配内存并初始化为零 (NULL)。为不可序列化类调用无参数构造函数,然后从流中恢复可序列化类的字段,从最接近 java.lang.object 的可序列化类开始,到对象最具体的类结束。

...

序列化不会读取或赋值给任何未实现 java.io.Serializable 接口的对象的字段。不可序列化的对象的子类可以是可序列化的。在这种情况下,不可序列化的类必须有一个无参数的构造函数来允许其字段被初始化。在这种情况下,子类负责保存和恢复不可序列化类的状态。通常情况下,该类的字段是可访问的(公共的、包的或受保护的),或者存在可用于恢复状态的 get 和 set 方法。

从文档中您可以看到您的选择是实现Serializable或添加无参数构造函数并为所有字段保留 getter 和 setter。

于 2013-05-13T22:36:40.800 回答