您的位置:首页 > 编程语言 > Java开发

Java常见序列化与反序列方法总结

2015-05-23 18:20 274 查看
人和电脑在很多方面都是十分相似的,大脑可以看成电脑主机,五官/身体等表面器官就是显示器、鼠标等外设。这篇文章就是想把计算机跟人做类比YY一下序列化和反序列化的机制、用途。

  如果你是初学者,心里肯定会问究竟什么是序列化/反序列化?其实我现在正在雨林木风xp系统下载序列化而你正在反序列化:我在写这篇博客的时候就是把大脑中的想法和思想经过梳理写成连续的文字,这就是序列化,而你在读这篇博客的时候把这些整理过的文字读进大脑形成你自己的思想,这个过程就是反序列化。
我们可以把大脑中的想法通过文字或声音传递,这样有“共同语言”的人就能将这些文字,声音"读"进大脑形成自己的思想,这就是 人与人之间“沟通、交流”的过程;为了防止记忆丢失我们通常会把自己的一些想法、知识以文字形式或声音进行“保存”。 计算机中序列化的定义是:把对象转换成数据流以便在网络上进行传输,或者将对象持久的存储在某个地方的过程;相反,反序列化是接收数据流转换成对应的对象或从持久化存储读取数据转换成对象的过程。简单来说序列化就是用来做"有意义"的存储或通信的。在Java中我们可以把一个对象序列化到网络流,文件流,也可以序列化到字节数组等,然后可以从网络流、文件流和字节数组等反序列化生成相应的对象。

  上面已经提到序列化、反序列化主要用于对象的持久化存储和远程通信。尤其在分布式系统中,应用十分广泛。

  下面对Java默认实现的序列化机制做一个由浅入深的介绍。

  a.首先是序列化机制的目标,下面是官方说明:

  1.简单且易于扩展;

  2.序列化形式能够保证Java对象类型信息和安全属性信息不丢失;

  3.方便扩展支持marshalling和unmarshalling,这是实现远程对象的基础;

  4.易于扩展,能方便实现Java对象的持久化;

  5.针对不同类的对象提供可定制的持久化方式;

  6.允许对象定制自己的外部表示形式;

  b. java默认提供的序列化机制:

  1.序列化的基本步骤:

  FileOutputStream fos = new FileOutputStream(outputFile)

  1:ObjectOutputStream oos = new ObjectOutputStream(fos);

  2:oos.writeObject(object);

  3:oos.close();

  第一步是创建一个对象输出流oos,可以把对象序列化到文件、字节数组等,在构造oos时赋予不同类型的流参数即可。

  在ObjectOutputStream的JDK实现中可以看出,构造oos对象时有安全管理器的校验、设置流格式(包括设置流的头信息:两个MagicNumber)。

  第二步就是写入需要序列化的对象,这一步也是最为复杂的,包含了序列化机制的细节信息。

  第三步关闭流。

  第一步创建对象输出流的时候,其实会初始化两个Table:HandleTable和ReplaceTable,HandleTable主要是为了防止相同对象数据的重复写入而设计。其中保存了原始对象到标志此对象index的映射,这样碰到重复的对象时写入的实际上是这个index而非原始对象数据。还可以对原始序列化对象进行替换,ReplaceTable用来保存被替换对象的信息。

  序列化机制里面有很多细节值得去挖掘:

  比如:1.Java中的引用到底是什么,而序列化对象的时候如何消除重复对象的保存。

  2.对于cycle reference的情况又是如何处理的。

  后面将做更加详细的分析。

  很多商业项目用到数据库、内存映射文件和普通文件来完成项目中的序列化处理的需求,但是这些方法很少会依靠于Java序列化。本文也不是用来解释序列化的,而是一起来看看面试中有关序列化的问题,这些问题你很有可能不了解。“Java序列化指的是将对象转换程字节格式并将对象状态保存在文件中,通常是.ser扩展名的文件。然后可以通过.ser文件重新创建Java对象,这个过程为返序列化”

  Java序列化的API中提供了开发人员进行序列化对象的机制,通过Serializable和Externalizable接口。

  一起看看这些问题:

  1)Java中的Serializable接口和Externalizable接口有什么区别?

  这个是面试中关于Java序列化问的最多的问题。我的回答是,Externalizable接口提供了两个方法writeExternal()和readExternal()。这两个方法给我们提供了灵活处理Java序列化的方法,通过实现这个接口中的两个方法进行对象序列化可以替代Java中默认的序列化方法。正确的实现Externalizable接口可以大幅度的提高应用程序的性能。

  2)Serializable接口中有借个方法?如果没有方法的话,那么这么设计Serializable接口的目的是什么?

  Serializable接口在java.lang包中,是Java序列化机制的核心组成部分。它里面没有包含任何方法,我们称这样的接口为标识接口。如果你的类实现了Serializable接口,这意味着你的类被打上了“可以进行序列化”的标签,并且也给了编译器指示,可以使用序列化机制对这个对象进行序列化处理。

  3)什么是serialVersionUID?如果你没有定义serialVersionUID意味着什么?

  SerialVersionUID应该是你的类中的一个public static final类型的常量,如果你的类中没有定义的话,那么编译器将抛出警告。如果你的类中没有制定serialVersionUID,那么Java编译器会根据类的成员变量和一定的算法生成用来表达对象的serialVersionUID
,通常是用来表示类的哈希值(hash code)。结论是,如果你的类没有实现SerialVersionUID,那么如果你的类中如果加入或者改变成员变量,那么已经序列化的对象将无法反序列化。这是以为,类的成员变量的改变意味这编译器生成的SerialVersionUID的值不同。Java序列化过程是通过正确SerialVersionUID来对已经序列化的对象进行状态恢复。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: