什么叫序列化,如何实现序列化以及反序列化(转)

原文连接:https://blog.csdn.net/u011215133/article/details/51177843java

 

简单来讲序列化就是一种用来处理对象流的机制。所谓对象流也就是将对象的网络

内容进行流化,流的概念这里不用多说(就是I/O)。咱们能够对流化后的对象进行读写spa

操做,也可将流化后的对象传输于网络之间(注:要想将对象传输于网络必须进行流化)!.net

在对对象流进行读写操做时会引起一些问题,而序列化机制正是用来解决这些问题的!code

-----------------------------------------------------------------------------------------小分割线
问题的引出:
如上所述,读写对象会有什么问题呢?好比:我要将对象写入一个磁盘文件然后再将对象

其读出来会有什么问题吗?别急,其中一个最大的问题就是对象引用!blog

举个例子来讲:假如我有两个类,分别是A和B,B类中含有一个指向A类对象的引用,接口

如今咱们对两个类进行实例化{ A a = new A(); B b = new B(); }。这时在内存中实际上分配内存

了两个空间,一个存储对象a,一个存储对象b。接下来咱们想将它们写入到磁盘的一个文件get

中去,就在写入文件时出现了问题!由于对象b包含对对象a的引用,因此系统会自动的将a

的数据复制一份到b中,这样的话当咱们从文件中恢复对象时(也就是从新加载到内存中)时,

内存分配了三个空间,而对象a同时在内存中存在两份,想想后果吧,若是我想修改对象a

的数据的话,那不是还要搜索它的每一份拷贝来达到对象数据的一致性,这不是咱们所但愿的!

-----------------------------------------------------------------------------------------小分割线
如下序列化机制的解决方案:
1.保存到磁盘的全部对象都得到一个序列号(1, 2, 3等等)

2.当要保存一个对象时,先检查该对象是否被保存了

3.若是之前保存过,只需写入"与已经保存的具备序列号x的对象相同"的标记,不然,保存该对象

经过以上的步骤序列化机制解决了对象引用的问题!

-----------------------------------------------------------------------------------------小分割线
序列化的实现
将须要被序列化的类实现Serializable接口,该接口没有须要实现的方法,implements Serializable

只是为了标注该对象是可被序列化的。而后使用一个输出流(如:FileOutputStream)来构造一个 

ObjectOutputStream(对象流)对象。接着,使用ObjectOutputStream对象的writeObject(Object obj)方法

就能够将参数为obj的对象写出(即保存其状态),要恢复的话则用输入流。

在序列化的过程当中,有些数据字段咱们不想将其序列化,对于此类字段咱们只须要在定义

时给它加上transient关键字便可,对于transient字段序列化机制会跳过不会将其写入文件,固然

也不可被恢复。但有时咱们想将某一字段序列化,但它在SDK中的定义倒是不可序列化的类型,

这样的话咱们也必须把他标注为transient,但是不能写入又怎么恢复呢?好在序列化机制为包含

这种特殊问题的类提供了以下的方法定义:

private void readObject(ObjectInputStream in) throws
IOException, ClassNotFoundException;
private void writeObject(ObjectOutputStream out) throws
IOException;
(注:这些方法定义时必须是私有的,由于不须要你显示调用,序列化机制会自动调用的)

使用以上方法咱们能够手动对那些你又想序列化又不能够被序列化的数据字段进行写出和读入操做。

======================================================================分割线

下面是一个典型的例子,java.awt.geom包中的Point2D.Double类就是不可序列化的,由于该类

没有实现Serializable接口,在个人例子中将把它看成LabeledPoint类中的一个数据字段,并演示

如何将其序列化!

 

package kunpu.serialize; import java.awt.geom.Point2D; import java.io.*; public class TransientTest { public static void main(String[] args) { LabeledPoint label = new LabeledPoint("Book", 5.00, 5.00); try { System.out.println(label); // 写入前 
                         ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("Label.txt")); out.writeObject(label);    //经过对象输出流,将label写入流中 
                         out.close(); System.out.println(label);// 写入后 
                         ObjectInputStream in = new ObjectInputStream(new FileInputStream("Label.txt")); LabeledPoint label1 = (LabeledPoint) in.readObject(); in.close(); System.out.println(label1);// 读出并加1.0后 
 } catch (Exception e) { e.printStackTrace(); } } } class LabeledPoint implements Serializable { private String label; transient private Point2D.Double point;    //由于不可被序列化,因此须要加transient关键字
  
         public LabeledPoint(String str, double x, double y)//构造方法 
 { label = str; point = new Point2D.Double(x, y);  //此类Point2D.Double不可被序列化 
 } //由于Point2D.Double不可被序列化,因此须要实现下面两个方法 
         private void writeObject(ObjectOutputStream out) throws IOException { out.defaultWriteObject(); out.writeDouble(point.getX()); out.writeDouble(point.getY()); } private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { in.defaultReadObject(); double x = in.readDouble() + 1.0; double y = in.readDouble() + 1.0; point = new Point2D.Double(x, y); } //重写toString方法 
         public String toString() { return getClass().getName()+ "[label = " + label+ ", point.getX() = " + (point == null ? "null" : point.getX())+ ", point.getY() = " + (point ==  null ? "null" : point.getY())+ "]"; } } 

 

序列化和反序列化是I/O的ObjectOutputStream和ObjectInputrStream进行实现的

相关文章
相关标签/搜索