串行化(serialization)是指将一个对象的当前状态转换成字节流(a stream of bytes)的过程,而反串行化(deserialization)则指串行化过程的逆过程,将字节流转换成一个对象,打回原形。
一、串行化的意义:
1:解决Web应用程序的无状态弊端
一旦将某一对象串行化,得到的字节可以存储在文件、数据库,或内存中—— 只要是可以存储的任何地方。需要恢复对象时,仅仅只需从它存储的位置反串行化即可。对象固有的这种特性对于无状态的Web应用程序是非常重要的,因为它允许重要的状态信息可以在用户请求之间保留。
2:应用程序边界之间传递对象
串行化也允许对象在应用程序边界之间传递,编程人员可以将描述对象状态的字节流在网络上传递,并在另一端反串行化成一个匹配的对象。从本质上讲,串行化允许对象以“数值”的方式传递给另一个应用程序。
二:串行化对象
在java中串行化对象必须:
1、该对象的类必须实现Serializable接口
2、该对象的串行化成员必须是非静态成员变量,即不能保存任何的成员方法和静态的成员变量,而且串行化保存的只是变量的值,对于变量的任何修饰符,都不能保存。而对于某些类型的对象,其状态是瞬时的,这样的对象是无法保存其状态的,例如一个Thread对象,或一个FileInputStream对象,对于这些字段,我们必须用transient关键字标明 。
注:保存任何的成员方法和静态的成员变量没有任何的意义,因为,对象的类已经完整的保存了他们,如果再串行化没有任何意义
3、要串行化一个对象,必须与一定的对象输入/输出流联系起来,通过对象输出流将对象状态保存下来,再通过对象输入流将对象状态恢复。
只有实现了Serializable接口的类才能够通过串行化进行保存和恢复。Serializable接口没有定义成员,这是简单的用于指示类可以被串行化。如果一个类是可以串行化的,那么这个类的所有子类也是可串行化的。
声明为transient的变量不能通过串行化进行保存。此外也不能保存static变量。
Java对串行化和反串行化功能进行了精心设计,从而使得许多保存和恢复对象状态的工作都可以自动运行。然而在有些情况下,程序员可能需要控制整个过程。例如,可能希望使用压缩和加密技术。Externailzable接口就是针对这些情况而设计的,此接口定义了下面两个构造方法:
void readExternal(ObjectInput instream)
throws IOException,ClassNotFoundException
void writeExternal(ObjectOutput outstream)
throws IOException
在这两个方法中,instream是从中读取对象的字节流,outstream是将对象写入其中的字节流
众所周知一个对象只要实现了Serilizable接口,这个对象就可以被序列化,java的这种序列化模式为开发者提供了许多便利,我们可以不必关心具体序列化的过程,只要这个类实现了Serilizable接口,这个类的所有属性与 方法都会自动序列化。
然而在实际开发过程中,我们常常会遇到这样的问题,这个类的有些属性需要序列化,而其他属性不需要被序列化,当然你可以让这个类来实现Externalizable接口,这个接口是Serilizable的子接口,但你必须实现readExternal和writeExternal方法,你可以在这两个方法中实现具体属性的序列化和反序列化操作。然而这就意味着你必须在这两个方法中手工编写额外的代码来进行具体属性的序列化。Java的transient关键字为我们提供了便利,你只需要实现Serilizable接口,将不需要序列化的属性前添加关键字transient,序列化属性的时候,这个属性就不会序列化指定的目的地中
import java.io.*; class MyClass implements Serializable{ String s; int i; transient double d; public MyClass(String s,int i,double d){ this.s=s; this.i=i; this.d=d; } public String toString(){ return "s="+s+"; i="+i+"; d="+d; } } class SerializarionDemo { public static void main(String[] args){ try(ObjectOutputStream objoStrm=new ObjectOutputStream(new FileOutputStream("c:serial.txt"))){ MyClass object1=new MyClass("Hello!你好",-7,2.7e10); System.out.println("object1: "+object1); objoStrm.writeObject(object1); }catch(IOException e){ System.out.println("Exception during serialiation: "+e); } try(ObjectInputStream objiStrm=new ObjectInputStream(new FileInputStream("c:serial.txt"))){ MyClass object2=(MyClass)objiStrm.readObject(); System.out.println("object2: "+object2); }catch(Exception e){ System.out.println("Exception deserialization: "+e); } } }