序列化中的继承问题


package tigers;

import java.io.*;


public class Tiger3 {
static class Sub extends Super {
private String name;
public Sub(int id, int uid, String name) {
super(id, uid);
this.name = name;
}
public String toString() {
return "Tiger3$Sub:(" + super.toString() + "," + name + ")";
}

private void writeObject(ObjectOutputStream oos) throws IOException {
System.out.println("Sub.writeObject()");
oos.defaultWriteObject();
}
private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
System.out.println("Sub.readObject()");
ois.defaultReadObject();
}
}
static class Super implements Serializable {
private int id;
private transient int uid;
public Super(int id, int uid) {
this.id = id;
this.uid = uid;
}
private static final long serialVersionUID = 1L;
private void writeObject(ObjectOutputStream oos) throws IOException {
System.out.println("Super.writeObject()");
oos.defaultWriteObject();
oos.writeInt(uid);
}
private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
System.out.println("Super.readObject()");
ois.defaultReadObject();
uid = ois.readInt();
}
public String toString() {
return "Tiger3$Super:(" + id + "," + uid + ")";
}
}
public static void main(String[] args) {
Tiger3.Super sup = new Tiger3.Super(55, 1000);
Tiger3.Sub sub = new Tiger3.Sub(12, 100, "sub");
try {
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("Tiger3$Super.tmp"));
oos.writeObject(sup);
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("Tiger3$Super.tmp"));
sup = (Tiger3.Super) ois.readObject();
System.out.println(sup);
oos = new ObjectOutputStream(new FileOutputStream("Tiger3$Sub.tmp"));
oos.writeObject(sub);
ois = new ObjectInputStream(new FileInputStream("Tiger3$Sub.tmp"));
sub = (Tiger3.Sub) ois.readObject();
System.out.println(sub);
} catch (IOException ioe) {

} catch (ClassNotFoundException cnfe) {

}
}
}

结果:

Super.writerObject()
Super.readObject()
Tiger3$Super:(55,1000)
Super.writerObject()
Sub.writeObject()

Super.readObject()
Sub.readObject()

Tiger3$Sub:(Tiger3$Super:(12,100),sub)

如果将Super和Sub中writeObject()和readObject()的修饰符改成public:

Tiger3$Super:(55,0)
Tiger3$Sub:(Tiger3$Super:(12,0),sub)


Tiger3$Super:(55,0)
Tiger3$Sub:(Tiger3$Super:(12,0),sub)


结论:

一、如果Super类包含需要序列化的primitive类型变量,应该实现writeObject()和readObject()方法,并在里面分别调用ObjectOutputStream.defaultWriteObject()和ObjectInputStream.defaultReadObject()方法。

二、writeObject()和readObject()的修饰符、返回类型、参数必须符合规定,即必须是如下格式:

private void writeObject(ObjectOutputStream o) throws...;

private void readObject(ObjectInputStream o) throws...;

否则这两个方法将不会被调用。

三、如果父类实现了Serializable接口,子类将自动得到可序列化特性。并且序列化子类时,父类的writeObject()和readObject()将得到调用。换言之,在序列化子类之前,父类将会自动被序列化。

/*
* Created on 2005-2-7
*
* TODO To change the template for this generated file go to
* Window - Preferences - Java - Code Style - Code Templates
*/
package tigers;

import java.io.*;

/**
* @author bitan
*
* TODO To change the template for this generated type comment go to
* Window - Preferences - Java - Code Style - Code Templates
*/
public class Tiger4 {
static class Super {
private String name;
public Super(String name) {
this.name = name;
}
public String toString() {
return "Tiger4$Super:(" + name + ")";
}
}
static class Sub extends Super implements Serializable {
private String name;
Sub (String superName, String name) {
super(superName);
this.name = name;
}
public String toString() {
return "Tiger4$Sub:("+ super.toString() + "," + name + ")";
}
}
public static void main(String[] args) {
Sub sub = new Sub("super","sub");
try {
System.out.println("序列化之前:" + sub);
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("Tiger4$Sub.tmp"));
oos.writeObject(sub);
System.out.println("序列化之后:" + sub);
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("Tiger4$Sub.tmp"));
sub = (Sub) ois.readObject();
System.out.println("反序列化之后:" + sub);
} catch (IOException ioe) {
ioe.printStackTrace();
} catch (ClassNotFoundException cnfe) {
cnfe.printStackTrace();
}
}
}

结果:

序列化之前:Tiger4$Sub:(Tiger4$Super:(super),sub)
序列化之后:Tiger4$Sub:(Tiger4$Super:(super),sub)

java.io.InvalidClassException: tigers.Tiger4$Sub; no valid constructor
at java.io.ObjectStreamClass.<init>(ObjectStreamClass.java:428)
at java.io.ObjectStreamClass.lookup(ObjectStreamClass.java:268)
at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1029)
at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:291)
at tigers.Tiger4.main(Tiger4.java:41)

给Super加上无参数构造函数

public Super() {

this.name = "default";

}

后:

序列化之前:Tiger4$Sub:(Tiger4$Super:(super),sub)
序列化之后:Tiger4$Sub:(Tiger4$Super:(super),sub)
反序列化之后:Tiger4$Sub:(Tiger4$Super:(default),sub)

现在,给Super的name字段加上Setter和Getter方法:

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

并且给Sub加上writeObject()和readObject()方法:

private void writeObject(ObjectOutputStream oos) throws IOException {
oos.defaultWriteObject();
oos.writeObject(super.getName());
}
private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
ois.defaultReadObject();
super.setName((String) ois.readObject());
}

结果:

序列化之前:Tiger4$Sub:(Tiger4$Super:(super),sub)
序列化之后:Tiger4$Sub:(Tiger4$Super:(super),sub)
反序列化之后:Tiger4$Sub:(Tiger4$Super:(super),sub)

结论:

一、当父类没有实现Serializable接口的前提下,序列化子类时父类将不会被自动序列化。而反序列化子类时,父类的无参数构造方法将会被调用。

二、如果想在序列化子类的同时也自动序列化父类中的字段,必须在子类的writeObject()和readObject()中相应实现。

### 继承序列化的概念 继承序列化指的是当一个类派生自另一个可序列化的基类时,子类不仅能够保存自身的成员变量到持久存储中,还可以自动处理来自父类的数据成员。这意味着,在执行序列化操作期间,整个对象图——包括超类部分以及当前实例特有的属性都将被记录下来;而在反序列化阶段,则会依据先前保存的信息重建完整的对象层次结构。 对于 Java 来说,只要确保所有参与其中的类都标记为 `Serializable` 接口即可完成这一功能[^1]。然而需要注意的是,默认机制下只会复制非瞬态(non-transient)、非静态字段的内容给子代节点。如果希望覆盖这种行为或者控制更精细粒度上的细节,开发者可以提供显式的 `writeObject()` 和 `readObject()` 方法来定制流程。 在 Hadoop 的 MapReduce 编程模型里,为了支持复杂的业务逻辑并提高灵活性,通常会让 bean 类遵循特定接口的要求以便于框架内部管理生命周期。例如实现了 `WritableComparable<T>` 或者仅仅是 `Writable` 接口之后,即使存在多层继承关系也依然可以通过标准 API 完成高效的数据交换工作[^2]。 至于基于 C++ 及其扩展库 Qt 开发的应用程序而言,虽然原生语言层面并没有像前者那样内置的支持方案,但是借助元对象系统 (Meta-Object System),仍然可以获得相当便捷的操作体验。通过注册相应的读取器/写入器函数并与信号槽机制相结合,即使是复杂嵌套的对象也可以轻松地转化为字节流形式加以存档或是网络传输[^3]。 ```cpp // 假设有一个简单的 BaseClass 已经具备基本的序列化能力 class Derived : public QObject, public BaseClass { Q_OBJECT public: explicit Derived(QObject *parent = nullptr); protected: void serialize(QDataStream &stream) const override; void deserialize(QDataStream &stream) override; private: int m_derivedData; // 子类特有数据项 }; ```
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值