从上面叙述中我们知道了对象序列化是java编程中必备武器那么让我们从基础开始好好学习下它机制和使用方法
java序列化比较简单通常不需要编写保存和恢复对象状态定制代码实现java.io.Serializable接口类对象可以转换成字节流或从字节流恢复不需要在类中增加任何代码只有极少数情况下才需要定制代码保存或恢复对象状态这里要注意:不是每个类都可序列化有些类是不能序列化例如涉及线程类和特定JVM有非常复杂关系
序列化机制:
序列化分为两大部分:序列化和反序列化序列化是这个过程第部分将数据分解成字节流以便存储在文件中或在网络上传输反序列化就是打开字节流并重构对象对象序列化不仅要将基本数据类型转换成字节表示有时还要恢复数据恢复数据要求有恢复数据对象例子ObjectOutputStream中序列化过程和字节流连接包括对象类型和版本信息反序列化时JVM用头信息生成对象例子然后将对象字节流中数据复制到对象数据成员中下面我们分两大部分来阐述:
处理对象流:(序列化过程和反序列化过程)
java.io包有两个序列化对象类ObjectOutputStream负责将对象写入字节流ObjectInputStream从字节流重构对象
我们先了解ObjectOutputStream类吧ObjectOutputStream类扩展DataOutput接口
writeObject思路方法是最重要思路方法用于对象序列化如果对象包含其他对象引用则writeObject思路方法递归序列化这些对象每个ObjectOutputStream维护序列化对象引用表防止发送同对象多个拷贝(这点很重要)由于writeObject可以序列化整组交叉引用对象因此同ObjectOutputStream例子可能不小心被请求序列化同对象这时进行反引用序列化而不是再次写入对象字节流
下面让我们从例子中来了解ObjectOutputStream这个类吧
// 序列化 today's date 到个文件中. FileOutputStream f = FileOutputStream("tmp"); ObjectOutputStream s = ObjectOutputStream(f); s.writeObject("Today"); s.writeObject( Date); s.flush;
现在让我们来了解ObjectInputStream这个类它和ObjectOutputStream相似它扩展DataInput接口ObjectInputStream中思路方法镜像DataInputStream中读取Java基本数据类型公开思路方法readObject思路方法从字节流中反序列化对象每次readObject思路方法都返回流中下个Object对象字节流并不传输类字节码而是包括类名及其签名readObject收到对象时JVM装入头中指定类如果找不到这个类则readObject抛出ClassNotFoundException,如果需要传输对象数据和字节码则可以用RMI框架ObjectInputStream其余思路方法用于定制反序列化过程
例子如下:
//从文件中反序列化 对象和 date 对象 FileInputStream in = FileInputStream("tmp"); ObjectInputStream s = ObjectInputStream(in); String today = (String)s.readObject; Date date = (Date)s.readObject;
定制序列化过程:
序列化通常可以自动完成但有时可能要对这个过程进行控制java可以将类声明为serializable但仍可手工控制声明为或transient数据成员
例子:个非常简单序列化类
public simpleSerializableClass implements Serializable{ String sToday="Today:"; transient Date dtToday= Date; }
序列化时类所有数据成员应可序列化除了声明为transient或成员将变量声明为transient告诉JVM我们会负责将变元序列化将数据成员声明为transient后序列化过程就无法将其加进对象字节流中没有从transient数据成员发送数据后面数据反序列化时要重建数据成员(它是类定义部分)但不包含任何数据这个数据成员不向流中写入任何数据记住对象流不序列化或transient我们类要用writeObject和readObject思路方法以处理这些数据成员使用writeObject和readObject思路方法时还要注意按写入顺序读取这些数据成员
有关如何使用定制序列化部分代码如下:
//重写writeObject思路方法以便处理transient成员 public void writeObject(ObjectOutputStream outputStream) throws IOException{ outputStream.defaultWriteObject;//使定制writeObject思路方法可以 利用自动序列化中内置逻辑 outputStream.writeObject(oSocket.getInetAddress); outputStream.writeInt(oSocket.getPort); } //重写readObject思路方法以便接收transient成员 private void readObject(ObjectInputStream inputStream) throws IOException,ClassNotFoundException{ inputStream.defau
最新评论