序列化

无意当中想到这个问题,然后 google 一下。找到一篇对 serialization 介绍的文章,关于这个问题比较多的人解释是: hibernate 有二级缓存,缓存会将对象写进硬盘,就必须序列化,以及兼容对象在网络中的传输 等等 ...

    
目的:将二级缓存中的内容持久化保存下来,便于恢复缓存的信息, hibernate 的缓存机制通过使用序列化,断定应该是基于序列化的缓存,如没有 serializable 接口,在序列化时,使用 objectOutputStreamwriteobject )方法将对象保存到文件时将会出现异常。  
      java
中常见的几个类(如: IntergerString 等),都实现了 serializable 接口  
   接口 java.io.Serializable 
      
      public interface Serializable 
   实现 java.io.Serializable 接口的类是可序列化的。没有实现此接口的类将不能使它们的任一状态被序列化或逆序列化。序列化类的所有子类本身都是可序列化的。这个序列化接口没有任何方法和域,仅用于标识序列化的语意。  
   控制序列化的时候还可能会碰到,要禁止 Java 的序列化机制自动存取某个子对象的情况。这种需求是很常见的,你肯定不会希望把口令之类敏感信息也序列化了。因为一旦序列化了,别人就能通过分析文件和截获网络传输来进行破解,这样即便访问权限是 private 的也保不住了。
   序列化就是一种用来处理对象流的机制,所谓对象流也就是将对象的内容进行流化。可以对流化后的对象进行读写操作,也可将流化后的对象传输于网络之间。序列化是为了解决在对对象流进行读写操作时所引发的问题。  
   序列化的实现:将需要被序列化的类实现 Serializable 接口,该接口没有需要实现的方法, implements Serializable 只是为了标注该对象是可被序列化的,然后使用一个输出流 ( 如: FileOutputStream) 来构造一个 ObjectOutputStream( 对象流 ) 对象,接着,使用 ObjectOutputStream 对象的 writeObject(Object obj) 方法就可以将参数为 obj 的对象写出 ( 即保存其状态 ) ,要恢复的话则用输入流。  
   
   序列化 : 序列化是将对象转换为容易传输的格式的过程。例如,可以序列化一个对象,然后使用 HTTP 通过 Internet 在客户端和服务器之间传输该对象。在另一端,反序列化将从该流重新构造对象。
是对象永久化的一种机制。  
   确切的说应该是对象的序列化,一般程序在运行时,产生对象,这些对象随着程序的停止运行而消失,但如果我们想把某些对象(因为是对象,所以有各自不同的特性)保存下来,在程序终止运行后,这些对象仍然存在,可以在程序再次运行时读取这些对象的值,或者在其他程序中利用这些保存下来的对象。这种情况下就要用到对象的序列化。  
   只有序列化的对象才可以存储在存储设备上。为了对象的序列化而需要继承的接口也只是一个象征性的接口而已,也就是说继承这个接口说明这个对象可以被序列化了,没有其他的目的。之所以需要对象序列化,是因为有时候对象需要在网络上传输,传输的时候需要这种序列化处理,从服务器硬盘上把序列化的对象取出,然后通过网络传到客户端,再由客户端把序列化的对象读入内存,执行相应的处理。  

   对象序列化是 java 的一个特征,通过该特征可以将对象写作一组字节码,当在其他位置读到这些字节码时,可以依此创建一个新的对象,而且新对象的状态与原对象完全相同。为了实现对象序列化,要求必须能够访问类的私有变量,从而保证对象状态能够正确的得以保存和恢复。相应的,对象序列化 API 能够在对象重建时,将这些值还原给私有的数据成员。这是对 java 语言访问权限的挑战。通常用在服务器客户端的对象交换上面,另外就是在本机的存储。  
   对象序列化的最主要的用处就是在传递 , 和保存对象 (object) 的时候 , 保证对象的完整性和可传递性。譬如通过网络传输 , 或者把一个对象保存成一个文件的时候 , 要实现序列化接口 。  
   即使你没有用过对象序列化( serialization ),你可能也知道它。但你是否知道 Java 还支持另外一种形式的对象持久化,外部化( externalization )?

下面是序列化和外部化在代码级的关联方式:

public interface Serializable {}

public interface Externalizable extends Serializable {
void readExternal(ObjectInput in);
void writeExternal(ObjectOutput out);
}

比较 java.io.Externalizablejava.io.Serializable 序列化和外部化的主要区别

外部化和序列化是实现同一目标的两种不同方法。下面让我们分析一下序列化和外部化之间的主要区别。

通过 Serializable 接口对对象序列化的支持是内建于核心 API 的,但是 java.io.Externalizable 的所有实现者必须提供读取和写出的实现。 Java 已经具有了对序列化的内建支持,也就是说只要制作自己的类 java.io.SerializableJava 就会试图存储和重组你的对象。如果使用外部化,你就可以选择完全由自己完成读取和写出的工作, Java 对外部化所提供的唯一支持是接口:

voidreadExternal(ObjectInput in)
void writeExternal(ObjectOutput out)

现在如何实现 readExternal() writeExternal() 就完全看你自己了。

序列化会自动存储必要的信息,用以反序列化被存储的实例,而外部化则只保存被存储的类的标识。当你通过 java.io.Serializable 接口序列化一个对象时,有关类的信息,比如它的属性和这些属性的类型,都与实例数据一起被存储起来。在选择走 Externalizable 这条路时, Java 只存储有关每个被存储类型的非常少的信息。

每个接口的优点和缺点

Serializable
接口

·
优点:内建支持

·
优点:易于实现

·
缺点:占用空间过大

·
缺点:由于额外的开销导致速度变比较慢

Externalizable
接口

·
优点:开销较少(程序员决定存储什么)

·
优点:可能的速度提升

·
缺点:虚拟机不提供任何帮助,也就是说所有的工作都落到了开发人员的肩上。

在两者之间如何选择要根据应用程序的需求来定。 Serializable 通常是最简单的解决方案,但是它可能会导致出现不可接受的性能问题或空间问题;在出现这些问题的情况下, Externalizable 可能是一条可行之路。

要记住一点,如果一个类是可外部化的( Externalizable ),那么 Externalizable 方法将被用于序列化类的实例,即使这个类型提供了 Serializable 方法:

private void writeObject()
private void readObject()

再补充一点:

equals/hashcode
查看 JDK 文档,大致是用于你可以自己定义两个对象何时相等 (equals) 。例如你可以定义身份证相同的两个 Person 对象是相等的。重载 equals 同时,必须重写 hashCode

Serializable
接口是表明这个对象可以序列化,或者说可以把对象从内存中写入文件,或者通过网络传输。这是 EJB 规范的要求,保证可以这些对象在网络传输,进行远程调用
重写 hashCode 是因为, hibernate 有自己的 hashCode 算法,主要是用来区分 pojo 的各种状态,比如游离态等等。
序列化的接口最好每个 pojo 都实现,不一定非要复合主键。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值