对象序列化的含义和意义

序列化机制允许将实现序列化的Java对象转换成字节序列 ,这些字节序列可以被保存在磁盘上,或者通过网络传输,

以备以后重新恢复成原来的对象.

1.对象的序列化(serialize)指将一个Java对象写入IO流中,对象的反序列化机制(Deserialize)则指从IO流中恢复该Java对象.

如果需要让某个对象可以支持序列化机制,必须让它的类是可序列化的(实现Serialize接口或者Externalizable接口)

一.使用对象流实现序列化

    ObjectOutputStream oos=new ObjectOutputStream( new FileOutputStream("..."));//输出流(处理流)

    oos.writeObject(new Object())//对象输出到输出流中

二.使用对象流反序列化

    ObjectInputStream ois=new ObjectInputStream( new FileInputStream("..."));//输入流

    Object obj=ois.readObject();//从IO流中读取该Java对象,完成反序列化机制

2.对象引用的序列化

    1)如果某个类的基本类型是另一个引用类型,那么这个引用类型必须是可序列化的,否则拥有该类型属性类是不可序列化的.

    2)   Java序列化算法:

        所有保存到磁盘的对象都有一个序列化编号,  当程序试图序列化一个对象时,程序先检查该对象是否已经被序列化过了,只有当该对象从未被序列化过,系统才会将该对象转换成字节序列并输出.  如果某个对象已经被序列化过了,程序将只是输出一个序列化编号,而不是再次重新序列化该对象.

    3)由于Java的序列化机制,当程序序列胡一个可变对象时,只有第一次使用writeObject方法输出时才会将该对象转换成字节序列并输出,即使后面该对象的属性已经改变,程序再次调用writeObject方法时,只是输出一个序列化编号,所以改变的属性值不会被输出.

三.自定义序列化

    当对某个对象进行序列化时,系统会自动把该对象的所有属性依次进行序列化,如果某个属性引用到另一个对象,则被引用的对象也会被序列化,如果被引用的对象属性也引用了其他对象,则被引用的对象也会被序列化,这种被称为递归序列化.

1)被transient修饰的属性,Java对该属性不进行序列化.  被transient修饰的属性将被完全隔离在序列化机制外,在反序列化恢复该Java对象时无法获得该属性值.

        transient关键字只能用于修饰属性,不可修饰Java中其他成分.

2)Java提供了另外一种序列化机制,通过这种自定义序列化机制可以让程序控制如何序列化各属性,甚至完全不序列化某些属性.

   

    

//上述代码为自定义序列化

writeObject方法负责写入特定类的实例状态, 以便相应的readObject可以恢复它. 通过重写该方法, 可以完全获得对序列化机制的控制.(可以自主决定哪些属性需要序列化,如何序列化)

readObject方法负责从流中读取并恢复对象属性, 通过重写该方法, 可以完全获得对反序列化机制的控制,(自主决定需要反序列化哪些属性,如何反序列化)

<注意>当序列化流不完整时, readObjectNoData 方法可以用来正确地初始化反序列化对象, 例如,当接收方使用的反序列化类的版本不同于发送方, 或者序列化流被篡改时, 系统都会调用 readObjectNoData 方法来初始化反序列化对象.

writeObject 方法存储属性的顺序应该和 readObject方法中恢复属性的顺序一致, 否则不能正常恢复该对象.

3)更彻底的序列化机制

    如果需要在实现序列化某对象时替换该对象, 应为序列化类提供 Object writeReplace() 方法.

    Java的序列化机制保证在序列化某个对象之前, 先调用该对象的 writeReplace()方法, 如果该方法返回另一个Java对象, 系统

    将再次调用另一个对象的writeReplace方法, 直到该方法不再返回另一个对象为止. 程序最后将调用该对象的 writeObject 方法来保存该对象的状态.

      

//序列化机制在序列化Person对象时, 实际是转换为序列化 ArrayList对象

<注意>与writeReplace()方法相对的是, 序列化机制中还有一个特殊的方法, 可以实现保护性复制整个对象.

Object readResolve() 方法会紧接着readObject() 之后被调用, 该方法的返回值将会代替原来反序列化的对象, 而原来readObject 反序列化对象将会被立即丢弃.


四.使用 Externalizable 接口实现自定义序列化机制

Java提供了另一种序列化机制,这种序列化方式完全由程序员决定存储和恢复对象数据. 要实现该目标,Java类必须实现Externalizable接口.

1)Externalizable接口强制自定义序列化.

   

<重点>1.程序需要序列化实现Externalizable接口的对象, 一样调用ObjectOutputStream 的writeObject()方法输出该对象;反序列化该对象

,调用ObjectInputStream 的readObject()方法即可.

      2.需要实现序列化的类,最好给出无参构造,否则程序会出现InvalidClassException异常.


   
    
五.两种序列化机制的对比

    实现Serializable接口                                            实现Externalizable接口
                        

    系统自动存储必要信息                                        程序员决定存储哪些信息(自定义序列化)


    Java内建支持,易于实现,只需实现该接口                提供两个空方法,实现该接口必须为两个空方法提供实现
    即可,无序任何代码支持

    
    性能略差                                                            性能略高


<注意>虽然实现Externalizable接口能带来性能提升, 但由于该接口提升了编程的复杂度, 所以实际开发中大多使用Serializable接口来实现
序列化.

六.(重点)关于对象序列化的注意事项

    1)对象的类名,属性(包括基本类型,数组,对其他对象的引用)都会被序列化; 方法, static属性(静态属性), transient属性(瞬态属性)
    都不会被序列化.

    2)实现Serializable接口的类如果要想让某个属性不被序列化, 可用transient修饰该属性, 而不是用static修饰该属性.(虽然static)
    也能达到这样的效果, 但static不能这样用.

    3)保证序列化对象的属性的类型也是可序列化的, 否则, 该类是不可序列化的.

    4)反序列化对象时必须有对象的class文件.

    5)当通过文件或者网络来读取序列化后对象时,必须按实际写入的顺序读取.


七.版本

反序列化对象时必须提供该对象的class文件, 有时随着项目的升级, 系统的class 文件也会升级, Java为了保证两个class文件的兼容性

Java序列化机制允许为序列化类提供一个private static final 的 serialVersionUID 属性值, 该属性值用于标识该Java类的序列化版本,

当一个类升级后, 只要它的serialVersionUID属性值保持不变, 序列化机制也会把它们当成同一个序列化版本.

<*>不显示定义serialVersionUID属性的另一个弊端是: 不利于在JVM之间的移植, 不同编译器计算该属性的计算策略可能不同, 即使该类

完全没有改变, 但因为JVM的不同, 也会出现序列化版本不兼容而无法正确反序列的现象.

<重点>对类的修改会导致该类反序列化失败时,应该为该类重新分配一个serialVersionUID属性值.

    对类的哪些修改会导致反序列失败,分两种情况:

    1)修改类时仅仅修改了方法, 静态属性或者瞬时属性, 则反序列化不受任何影响, 类定义无须修改serialVersionUID属性值.

    2)如果修改了类中的非静态 , 非瞬态属性, 则可能导致序列化版本不兼容.



    


  • 5
    点赞
  • 53
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值