1.序列化定义
序列化分为两大部分:序列化(serialization)和反序列化(deserialization)。序列化是将数据分解成字节流,以便存储在文件 中或在网络上传输。反序列化就是打开字节流并重构对象。对象序列化不仅要将基本数据类型转换成字节表示,有时还要恢复数据。恢复数据要求有恢复数据的对象 实例。ObjectOutputStream中的序列化过程与字节流连接,包括对象类型和版本信息。反序列化时,JVM用头信息生成对象实例,然后将对象 字节流中的数据复制到对象数据成员中。
2.主要涉及的类
ObjectOutputStream类扩展DataOutput接口。writeObject()方法是最重要的方法,用于对象序列化。如果对象包含其 他对象的引用,则writeObject()方法递归序列化这些对象。每个ObjectOutputStream维护序列化的对象引用表,防止发送同一对 象的多个拷贝。由于writeObject()可以序列化整组交叉引用的对象,因此同一ObjectOutputStream实例可能不小心被请求序列化 同一对象。
这时,进行反引用序列化,而不是再次写入对象字节流。例如:
ObjectOutputStream o = new ObjectOutputStream(new FileOutputStream("Login.out"));
o.writeObject(new Date());
o.close();
ObjectInputStream类扩展DataInput接口。ObjectInputStream中的方法镜像DataInputStream中读 取Java基本数据类型的公开方法。readObject()方法从字节流中反序列化对象。每次调用readObject()方法都返回流中下一个 Object。对象字节流并不传输类的字节码,而是包括类名及其签名。readObject()收到对象时,JVM装入头中指定的类。如果找不到这个类, 则readObject()抛出ClassNotFoundException。
ObjectInputStream in = new ObjectInputStream(new FileInputStream("Login.out"));
Date d = (Date) in.readObject();
3.定制序列化过程
序列化通常可以自动完成,但有时可能要对这个过程进行控制。java可以将类声明为serializable,但仍可手工控制声明为static或 transient的数据成员。 序列化时,类的所有数据成员应可序列化除了声明为transient或static的成员。将数据成员声明为transient后,java可以逐个关闭 序列化,用Bruce Eckel的话说“不用麻烦你保存或者恢复数据-------我自己会处理的!”
例如:
某个Login对象保存某个特定的登录会话信息,登录的合法性通过校验以后,我们想把数据保存下来,但是不保存密码。可以采用定制序列化方
法解决问题。
- import java.io.FileInputStream;
- import java.io.FileOutputStream;
- import java.io.ObjectInputStream;
- import java.io.ObjectOutputStream;
- import java.io.Serializable;
- import java.util.Date;
- public class Login implements Serializable {
- private Date date = new Date();
- private String username;
- private transient String password;
- public Login(String name, String pwd) {
- username = name;
- password = pwd;
- }
- public String toString() {
- String pwd = (password == null) ? "(n/a)" : password;
- return "Login info:\n username:" + username
- + "\n date:" + date
- + "\n password:" + pwd;
- }
-
- public static void main(String[] args) throws Exception{
- Login a=new Login("bread","bread");
- System.out.println("Login a="+a);
- ObjectOutputStream o=new ObjectOutputStream(new FileOutputStream("Login.out"));
- o.writeObject(a);
- o.close();
- Thread.sleep(1000);
- ObjectInputStream in=new ObjectInputStream(new FileInputStream("Login.out"));
- System.out.println("Recovering object at"+new Date());
- a=(Login)in.readObject();
- System.out.println("Login a="+a);
- }
- }
复制代码
执行结果如下:
Login a=Login info:
username:bread
date:Thu Oct 26 18:44:41 CST 2006
password:bread
Recovering object atThu Oct 26 18:44:44 CST 2006
Login a=Login info:
username:bread
date:Thu Oct 26 18:44:41 CST 2006
password:(n/a)
|