我尽力理解这个概念。但我无法弄清楚这件事:
如果父级没有no-arg构造函数且父级没有实现Serializable接口,那么如何序列化子类呢?
Parent.java
public class Parent {
private String parentString;
public Parent(String parentString) {
this.parentString = parentString;
parentString = "Parent";
}
public String getParentString(){
return parentString;
}
}
Child.java
public class Child extends Parent implements Serializable{
private String childString;
public Child(String childString) {
super(childString);
this.childString = childString;
}
public String getChildString(){
return childString;
}
}
TestSerialization.java
public class TestSerialization {
public static void main(String[] args) throws IOException, ClassNotFoundException{
Child child = new Child("Child");
FileOutputStream fos = new FileOutputStream(new File("file.ser"));
ObjectOutputStream oos = new ObjectOutputStream(fos);
oos.writeObject(child);
oos.close();
FileInputStream fis = new FileInputStream(new File("file.ser"));
ObjectInputStream ois = new ObjectInputStream(fis);
Object obj = ois.readObject();
ois.close();
Child castChild = (Child) obj;
System.out.println(castChild.getParentString());
System.out.println(castChild.getChildString());
}
}
在阅读对象时,它给了我一个异常,说java.io.InvalidClassException: test.Child; no valid constructor
。如何序列化这样的对象?
答案 0 :(得分:4)
如果某个对象的某个超类不是Serializable
且没有no-arg构造函数,则无法直接序列化该对象。来自文档:
为了允许序列化非可序列化类的子类型,子类型可以承担保存和恢复超类型的公共,受保护和(如果可访问)包字段的状态的责任。 只有当它扩展的类具有可访问的no-arg构造函数来初始化类的状态时,子类型才可以承担此责任。如果不是,则声明类Serializable是错误的案件。将在运行时检测到错误。
(强调我的)
如果你可以修改父类,那么你应该简单地添加适当的no-arg构造函数和/或让它适当地实现Serializable
。
如果无法修改父类,则可能需要考虑序列化代理类。您可以实现方法
Object writeReplace() throws ObjectStreamException;
在你的Child
中返回一个代理对象(将被序列化而不是Child
实例),并实现
Object readResolve() throws ObjectStreamException;
在代理类中返回等效的Child
实例。
答案 1 :(得分:0)
仅写出并恢复Serializable对象的字段。仅当对象具有将初始化非可序列化超类型字段的无参数构造函数时,才可以恢复该对象。如果子类可以访问超类的状态,它可以实现writeObject和readObject来保存和恢复该状态。
因此,您需要在Child中提供无参数构造函数以及可选的writeObject
和readObject
。
答案 2 :(得分:-1)
你真的需要两个类中的默认构造函数。此外,您必须使类Parent Serializable。
另一个建议:请看一下Parent的构造函数。在那里你重新分配参数。这将没有任何效果。