【问题标题】:XML Serialization and Empty ConstructorsXML 序列化和空构造函数
【发布时间】:2013-05-08 01:45:52
【问题描述】:

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

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

【问题讨论】:

    标签: java serialization xml-serialization


    【解决方案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
    

    【讨论】:

    • 谢谢,但我尝试使用它,但仍然遇到相同的异常。
    • 是的,我最近试过你的,效果很好。还是不知道为什么我的没有。
    【解决方案2】:

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

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

    XML解码器javadoc:

    XMLDecoder 类用于读取使用 XMLEncoder 和 ObjectInputStream 一样使用。

    ObjectInputStreamjavadoc:

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

    ...

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-07-02
      相关资源
      最近更新 更多