对象持久化(Persistence)就是 将对象保存到磁盘文件或者网络中,保存对象的过程实质上就是对象持久化的过程。
*
也就是记录对象的状态以便于将来具有再生的能力。 Java提供了对象流以实现对象的输入输出,也就是实现对象的持久化。
*
需要注意的是在使用对象流之前必须要将该对象序列化。所谓的序列化就是将对象的状态转化成字节流,并且以后可以通过这些值 再生成相同状态的对象。
*
简单来说序列化就是一种用来处理对象流的机制,而对象流也就是将对象的内容进行流化,我们可以对流化后的对象进行读取操作,
*
也可以将流化后的对象传输于网络之间。
*
* 对象序列化,只需要被序列化的类实现Serializable接口就可以了。
*
Serializable接口中没有任何的方法,让一个类实现该接口只是为了标注该对象是可以被序列化的,然后就可以对该对象进行持久化。
*
*
注意: 序列化只能保存对象的实例变量,但不能保存类的任何方法和类变量,并且保存的只是变量的值。 对于任何修饰符都不能保存。
*
有些类型的变量是瞬时的,这样的对象也是无法保存的,如:线程对象、或流对象。对于这样的变量,必须用transient关键字标明,否则编译器将报错。
*
* 任何被transient标明的成员变量,将不被保存。
*
考虑到序列化可能涉及对象保存在磁盘上或者网络上,对于一些保密的数据就要加上transient关键字。
*
*
*
对象序列化之后,必须与一定的对象输入/输出流联系起来,通过对象输出流将对象的状态保存下来,再通过对象输入流将对象的状态恢复。
*
java提供了ObjectInputStream
*
类和ObjectOutputStream类分别实现了ObjectInput和ObjectOutput。
*
ObjectOutput接口用writeObject
*
()方法,可以将对象的状态保存到输出流中。而ObjectInput接口用readObject()方法以从输入流中读入一个对象。
*
Demo:
1 package com.tai.io; 2 3 import java.io.FileInputStream; 4 import java.io.FileNotFoundException; 5 import java.io.FileOutputStream; 6 import java.io.ObjectInputStream; 7 import java.io.ObjectOutputStream; 8 import java.io.Serializable; 9 10 public class PersistenceDome 11 { 12 /** 13 * 对象持久化(Persistence)就是 将对象保存到磁盘文件或者网络中,保存对象的过程实质上就是对象持久化的过程。 14 * 也就是记录对象的状态以便于将来具有再生的能力。 Java提供了对象流以实现对象的输入输出,也就是实现对象的持久化。 15 * 需要注意的是在使用对象流之前必须要将该对象序列化。所谓的序列化就是将对象的状态转化成字节流,并且以后可以通过这些值 再生成相同状态的对象。 16 * 简单来说序列化就是一种用来处理对象流的机制,而对象流也就是将对象的内容进行流化,我们可以对流化后的对象进行读取操作, 17 * 也可以将流化后的对象传输于网络之间。 18 * 19 * 对象序列化,只需要被序列化的类实现Serializable接口就可以了。 20 * Serializable接口中没有任何的方法,让一个类实现该接口只是为了标注该对象是可以被序列化的,然后就可以对该对象进行持久化。 21 * 22 * 注意: 序列化只能保存对象的实例变量,但不能保存类的任何方法和类变量,并且保存的只是变量的值。 对于任何修饰符都不能保存。 23 * 有些类型的变量是瞬时的,这样的对象也是无法保存的,如:线程对象、或流对象。对于这样的变量,必须用transient关键字标明,否则编译器将报错。 24 * 25 * 任何被transient标明的成员变量,将不被保存。 26 * 考虑到序列化可能涉及对象保存在磁盘上或者网络上,对于一些保密的数据就要加上transient关键字。 27 * 28 * 29 * 对象序列化之后,必须与一定的对象输入/输出流联系起来,通过对象输出流将对象的状态保存下来,再通过对象输入流将对象的状态恢复。 30 * java提供了ObjectInputStream 31 * 类和ObjectOutputStream类分别实现了ObjectInput和ObjectOutput。 32 * ObjectOutput接口用writeObject 33 * ()方法,可以将对象的状态保存到输出流中。而ObjectInput接口用readObject()方法以从输入流中读入一个对象。 34 * 35 * @throws Exception 36 */ 37 public static void main(String[] args) throws Exception 38 { 39 Person p = new Person("张三", "Mauiie", "男"); 40 Person p2 = new Person("p2", "Mauiie", "男"); 41 Person p3 = new Person("p3", "Mauiie", "男"); 42 Student s = new Student("孙俪", "Mauiie", "女"); 43 Person temp = null; 44 Person temp2 = null; 45 Student stemp = null; 46 FileOutputStream fos = new FileOutputStream("c:/data.dat"); 47 ObjectOutputStream oos = new ObjectOutputStream(fos); 48 oos.writeObject(p); 49 oos.writeObject(p2); 50 // oos.writeObject(p3); 51 oos.writeObject(s); 52 oos.close(); 53 System.out.println("已经将p和s对象写入到了 c:/data.dat"); 54 55 FileInputStream fis = new FileInputStream("c:/data.dat"); 56 ObjectInputStream ois = new ObjectInputStream(fis); 57 58 temp = (Person) ois.readObject(); 59 temp2 = (Person) ois.readObject(); 60 stemp = (Student) ois.readObject(); 61 62 ois.close(); 63 System.out.println(temp.toString()); 64 System.out.println(stemp.toString()); 65 System.out.println(temp2.toString()); 66 } 67 } 68 69 class Person implements Serializable 70 { 71 String Pname; 72 transient String Pid; 73 String Psex; 74 75 public Person(String name, String ID, String sex) 76 { 77 this.Pname = name; 78 this.Pid = ID; 79 this.Psex = sex; 80 } 81 82 public String toString() 83 { 84 return "Name " + Pname + " ID " + Pid + " sex " + Psex; 85 } 86 } 87 88 class Student implements Serializable 89 { 90 String Sname; 91 transient String Sid; 92 String Ssex; 93 94 public Student(String name, String ID, String sex) 95 { 96 this.Sname = name; 97 this.Sid = ID; 98 this.Ssex = sex; 99 } 100 101 public String toString() 102 { 103 return "这是Student对象 " + "Name " + Sname + " ID " + Sid 104 + " sex " + Ssex; 105 } 106 }
运行结果:
已经将p和s对象写入到了 c:/data.dat Name 张三 ID null sex 男 这是Student对象 Name 孙俪 ID null sex 女 Name p2 ID null sex 男
值得注意的是:
使用缺省的serializetion的实现时,一个ObjectOutputStream的构造和一个ObjectInputStream的构造必须一一对应。
ObjectOutputStream的构造函数会向输出流中写入一个标识头,而ObjectInputStream会首先读入这个标识头。因此,多次以追加方式向一个文件中写入object时,该文件将会包含多个标识头。
所以用ObjectInputStream来deserialize这个ObjectOutputStream时,将产生StreamCorruptedException。
一种解决方法是可以构造一个ObjectOutputStream的子类,并覆盖writeStreamHeader()方法。被覆盖后的writeStreamHeader()方法应判断是否为首次向文件中写入object?
若是,则调用super.writeStreamHeader();若否,即以追加方式写入object时,则应调用ObjectOutputStream.reset()方法。
如果再向该文件增加对象,新写的对象就读不出了可以参照下面这篇博客,我也遇到这样的问题, 我看了之后也觉得十分受教
http://halzhang.iteye.com/blog/267917