在Java的世界里,创建好对象之后,只要需要,对象是可以长驻内存,但是在程序终止时,所有对象还是会被销毁。这其实很合理,但是即使合理也不一定能满足所有场景,仍然存在着一些情况,需要能够在程序不运行的情况下保持对象,所以序列化机制应运而生。

1. 为什么要有序列化

  简单来说序列化的作用就是将内存中的对象保存起来,在需要时可以重建该对象,并且重建后的对象拥有与保存之前的对象所拥有的信息相同。在实际应用中,对象序列化常会用在如下场景:

  • RPC框架的数据传输;
  • 对象状态的持久化保存;

  也许你会觉得,要达到这种持久化的效果,我们直接将信息写入文件或数据库也可以实现啊,为什么还要序列化?这是一个好问题,试想如果我们采用前面所述的方法,在序列化对象和反序列化恢复对象时,我们必须考虑如何完整的保存和恢复对象的信息,这里面会涉及到很多繁琐的细节,稍加不注意就可能导致信息的丢失。如果能够有一种机制,只要将一个对象声明为是“持久性”的,就能够为我们处理掉所有细节,这样岂不是很方便,这就是序列化要做的事情。Java已经将序列化的概念加入到语言中,本文的关于序列化的所有例子都是基于Java的。

  Java提供的原生序列化机制功能强大,有其自己的一些特点:

  • 序列化处理非常简单,只需将对象实现Serializable接口即可;
  • 能够自动弥补不同操作系统之间的差异,即可以在运行Windows系统的计算机上创建一个对象,将其序列化,然后通过网络将它发送给一台运行Unix系统的计算机,然后在那里准确地重新组装,不必担心数据在新的机器上表示会不同;
  • 对象序列化不仅会保存对象的“全景图”,而且能够追踪对象内所包含的所有引用,并保存那些对象;接着又能对对象内包含的每个这样的引用进行追踪,依此类推;
  • 对象序列化保存的是对象的”状态”,即它的成员变量,所以对象序列化并不会处理类中的静态变量;

2. 序列化机制的使用

  Java的对象序列化机制是将那些实现了Serializable接口的对象转换成一个字节序列,并能够在以后将这个字节序列完全恢复为原来的对象。

  要序列化一个对象,首先要创建一个OutputStream对象,然后将其封装在一个ObjectOutputStream对象内,接着只需调用writeObject()方法即可将对象序列化,并将序列化后的字节序列发送给OutputStream。要将一个序列还原为一个对象,则需要将一个InputStream封装在ObjectInputStream内,然后调用readObject(),该方法会返回一个引用,它指向一个向上转型的Object,必须向下转型才能直接使用。

  我们来看一个例子,如何序列化和反序列化对象。

复制代码
public class Worm implements Serializable{     private static Random rand = new Random(47);     private Data[] d = {         new Data(rand.nextInt(10)),         new Data(rand.nextInt(10)),         new Data(rand.nextInt(10))     };     private Worm next;     private char c;    public Worm(int i, char x){         System.out.println("Worm constructor: " + i);         c = x;         if(--i > 0){             next = new Worm(i,(char)(x + 1));         }     }     public Worm(){         System.out.println("Default constructor");     }     public String toString(){         StringBuilder result = new StringBuilder(":");         result.append(c);         result.append("(");         for(Data dat : d){             result.append(dat);         }         result.append(")");         if(next != null){             result.append(next);         }         return result.toString();     }     public static void main(String[] args) throws ClassNotFoundException, IOException{         Worm w = new Worm(6,'a');         System.out.println("w = " + w);         ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("worm.out"));         out.writeObject("Worm storage\n");         out.writeObject(w);         out.close();         ObjectInputStream in = new ObjectInputStream(new FileInputStream("worm.out"));         String s = (String)in.readObject();         Worm w2 = (Worm)in.readObject();         System.out.println(s + "w2 = " + w2);         ByteArrayOutputStream bout = new ByteArrayOutputStream();         ObjectOutputStream out2 = new ObjectOutputStream(bout);         out2.writeObject("Worm storage\n");         out2.writeObject(w);         out2.flush();         ObjectInputStream in2 = new ObjectInputStream(new ByteArrayInputStream(bout.toByteArray()));         s = (String)in2.readObject();         Worm w3 = (Worm)in2.readObject();         System.out.println(s + "w3 = " + w3);     } }  class Data implements Serializable{     private int n;     public Data(int n){this.n = n;}     public String toString(){return Integer.toString(n);} }
复制代码

  输出结果如下: