在Java编程中,对象字节流(Object Streams)是用于序列化和反序列化Java对象的重要工具。对象序列化是将对象的状态信息转换为字节序列,以便存储或在网络中传输,而反序列化则是将这些字节序列重新转换回原始对象。本文主要关注的是如何使用`ObjectOutputStream`和`ObjectInputStream`来实现这一过程。
首先,`ObjectOutputStream`是Java提供的一个用于将Java对象写入字节流的类。例如,在提供的代码片段中,创建了一个`ObjectOutputStream`对象,并将其连接到一个名为"employee.dat"的文件。接着,两个对象`Employee`和`Manager`被实例化,并通过`writeObject()`方法被序列化到文件中。这个过程不仅保存了对象的类型(如`Employee`和`Manager`),还包括它们的属性值,如姓名、薪水等,以及任何自定义的序列化逻辑,如果对象实现了`Serializable`接口并重载了`writeObject()`方法的话。
`Serializable`接口是Java提供的一个标准接口,表示一个类可以被序列化。当一个类实现了这个接口,意味着它的所有非transient成员变量(即在序列化期间不会被忽略的字段)都将被保存。对于实现了`Serializable`但未提供自定义序列化逻辑的类,`ObjectOutputStream`会调用默认的`writeObject()`方法进行序列化。
另一方面,`ObjectInputStream`负责从字节流中读取并重构对象。当需要恢复保存的对象时,程序首先创建相应类型的空对象,然后使用`readObject()`方法读取文件中的数据,填充到新创建的对象中。对于实现了`Externalizable`接口的对象,反序列化过程会先调用缺省构造函数,然后调用`readExternal()`方法,这允许对象更精细地控制自己的反序列化过程。
在处理自定义序列化时,如果一个类仅实现了`Serializable`接口,而没有覆盖`writeObject()`和`readObject()`,则默认的行为可能不够理想。在这种情况下,为了确保非transient部分的正确保存和恢复,程序需要调用`defaultWriteObject()`和`defaultReadObject()`方法,它们是`Serializable`类的内置机制。此外,如果类希望完全控制序列化流格式和内容,就需要实现`Externalizable`接口,通过自定义的`writeExternal()`和`readExternal()`方法来管理。
总结来说,对象字节流在Java中扮演着关键角色,它使得复杂对象的存储和网络通信变得可行。理解序列化和反序列化的原理,包括`ObjectOutputStream`、`ObjectInputStream`、`Serializable`和`Externalizable`接口的使用,对于编写可维护和可扩展的Java应用程序至关重要。