为何须要序列化??(转)

为何须要序列化

注意:“为避免编译错误,为可序列化的类添加了无参数构造函数。” html

MSDN的定义:序列化是将对象状态转换为可保持或可传输的形式的过程。序列化的补集是反序列化,后者将流转换为对象。这两个过程一块儿保证数据易于存储和传输。 java

你们关心的是为何须要序列化,用传统的方法也能实现这种需求吗,它存在的价值是什么,低层的原理、实质、基因的区别是什么?这也是个人疑问,经过在网上搜集,找到了较满意的答案,分享给你们。 编程

答案一:序列化是用来通讯的,服务端把数据序列化,发送到客户端,客户端把接收到的数据反序列化后对数据进行操做,完成后再序列化发送到服务端,服务端再反序列化数据后对数据进行操做。说白了,数据须要序列化之后才能在服务端和客户端之间传输。这个服务端和客户端的概念是广义的,能够在网络上,也能够在同一台机器的不一样进程中,甚至在同一个进程中进行通讯。在传统编程中,对象是经过调用栈间接的与客户端交互,但在面向服务的编程中,客户端永远都不会直接调用实例。不知道说的明不明白。 

好吧,我说的确实不够明白,你问的是为何须要序列化,我只是说了序列化的一个应用。那我就来讲说序列化的好处吧。不序列化也能够传输,可是没法跨平台,安全性也没法保障。我说的是面向服务编程中的做用,在传统编程中,你在表示层实例化一个业务对象,而后调用业务对象中的方法,你想过为何能这样调用吗?这样作耦合度过高,很很差。若是序列化之后经过特定的协议传输数据就不同了,表示层经过代理或通道向服务层发送特定的数据格式,这个数据就是序列化之后的,好比XML,服务端接收到之后要进行反序列化,生成服务端可识别的数据格式,好比一个类,而后对数据进行操做,再序列化发送到客户端,客户端再反序列化。这样客户端可使用和服务端彻底不一样的开发平台,只要它可以对xml数据进行反序列化,而xml是具备工业标准的数据格式,基本各平台都支持。这也适用于在进程间通讯。若是在进程内通讯,也能够作到更高的安全性,对象再也不经过调用栈交互,而是经过代理或通道。 安全

转自:http://zhidao.baidu.com/question/311731521.html 网络

答案二:这个更进一步的解释了其真正的价值。 函数

简单来讲序列化就是一种用来处理对象流的机制,所谓对象流也就是将对象的内容进行流化,流的概念这里不用多说(就是I/O),咱们能够对流化后的对象进行读写操做,也可将流化后的对象传输于网络之间(注:要想将对象传输于网络必须进行流化)!在对对象流进行读写操做时会引起一些问题,而序列化机制正是用来解决这些问题的!

问题的引出:

如上所述,读写对象会有什么问题呢?好比:我要将对象写入一个磁盘文件然后再将其读出来会有什么问题吗?别急,其中一个最大的问题就是对象引用!举个例子来讲:假如我有两个类,分别是A和B,B类中含有一个指向A类对象的引用,如今咱们对两个类进行实例化{ A a = new A(); B b = new B(); },这时在内存中实际上分配了两个空间,一个存储对象a,一个存储对象b,接下来咱们想将它们写入到磁盘的一个文件中去,就在写入文件时出现了问题!由于对象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类中的一个数据字段,并演示如何将其序列化!

import java.io.*;

import java.awt.geom.*;

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);
                         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
{
         public LabeledPoint(String str, double x, double y)
         {
                 label = str;
                 point = new Point2D.Double(x, y);
         }

         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);

         }

         public String toString()
         {
                 return getClass().getName()+ "[label = " + label+ ", point.getX() = " + point.getX()+ ", point.getY() = " + point.getY()+ "]";
         }
         private String label;
         transient private Point2D.Double point;
}转自: http://blog.sina.com.cn/s/blog_5b142cae0100clon.html

总结:对象序列化,就是保证多处须要使用的对象,若是是同一个,就只实例化一次,这样,效率高,若是对象发生了变化,只要序列化的对象流发生对应的变法便可。 spa

什么状况下使用: 代理

有两个最重要的缘由促使对序列化的使用:一个缘由是将对象的状态保持在存储媒体中,以即可以在之后从新建立精确的副本;另外一个缘由是经过值将对象从一个应用程序域发送到另外一个应用程序域中。 xml

 参考:http://www.cnblogs.com/gaozhongfa/archive/2009/12/08/1619041.html htm

相关文章
相关标签/搜索