Java对象序列化

来源:互联网 发布:a标签触发js函数 编辑:程序博客网 时间:2024/06/05 01:10

Serializable接口

Serializable接口只是一个标记接口,不包含任何的方法。

Java的对象序列化是指将那些实现Serializable接口的对象转化成一个字节序列,并能够用这个字节序列完全恢复为原来的对象。这种序列化机制能自动弥补不同操作系统之间的差异。

序列化

对象转成字节

  1. 创建某种OutputStream,例FileOutputStream、ByteArrayOutputStream等。
  2. 用ObjectOutputStream封装使用的OutputStream。
  3. 调用writeObject()进行对象序列化。

反序列化

字节转对象

  1. 创建某种InputStream,例FileInputstream、ByteArrayInputStream等。
  2. 用ObjectInputStream封装使用的InputStream。
  3. readObject()进行反序列化。

对象的序列化是基于字节的,不能使用Reader和Writer等基于字符的层次结构。
在进行反序列的时候,Serializable对象完全以它存储的二进制位作为基础来构造,而不调用构造器(构造方法)。

序列化前的对象与反序列还原后对象的关系

属于深度复制

  • 浅复制:被复制对象的所有变量都含有与原来的对象相同的值,而所有的对其他对象的引用仍然指向原来的对象。换言之,浅复制仅仅复制所考虑的对象,而不复制它所引用的对象。
  • 深复制:被复制对象的所有变量都含有与原来的对象相同的值,除去那些引用其他对象的变量。那些引用其他对象的变量将指向被复制过的新对象,而不再是原有的那些被引用的对象。换言之,深复制把要复制的所引用对象的对象都复制了一遍。

序列化前的对象与反序列还原后对象的地址不一样,而两个对象中的引用也不一样,但是值都一样。换句话说,通过序列化操作,我们可以实现对任何Serializable对象的”深度复制(deep copy)”——这意味着我们复制的是整个对象网,而不仅仅是基本对象及其引用。

对于用同一个IO流进行序列化操作的Serializable对象,他们的地址是一样的,同一对象,与用其他IO流的Serializable对象地址却不相同。
只要将对象序列化到单一流中,就可以恢复出原来对象一样的对象网,而且只要在同一流中,对象都是同一个。

serialVersionUID

UID:stream unique identifier

在Java中SerialVersionUID是唯一控制着能否反序列化成功的标志,只要这个值不一样,就无法反序列化。

向上兼容性

旧版本的Serializable对象能读取新版本的Serializable对象序列化后的数据流(二进制)。

  • 新数据流中的多余的内容将会被忽略;
  • 但是在新版本的Serializble对象中修改了老版本的Serializable对象的内容,即使UID不变,也会报异常。

向下兼容性

新版本的Serializable对象能读取旧版本的Serializable对象序列化后的数据流(二进制)。

  • 旧的数据流中包含的所包含的所有内容将会被恢复,新版本的类中没有涉及到的部分将保持默认值。
  • 对于那些没有默认值进行初始化的参数,需要进行初始化操作。
private void readObject(java.io.ObjectInputStream in) throws IOException,ClassNotFoundException{    in.defaultReadObject();//先反序列化对象    if(version=123){        //初始化其他字段    }else if(version=456){        //初始化其他字段    }else{        //太老的版本不支持        throw new InvalidClassException();    }}

要保证in.defaultReadObject()的执行,要求serialVersionUID保持一致,所以version不能使用serialVersionUID,version是我们预先设置的,final long version=xxxx。

保持向下兼容性的要求
1. serialVersionUID保持一致。
2. 预先设置好我们自己的版本识别标记的final long version=xxxx。
3. 保证对象的所有字段都得到了初始化。

serialVersionUID做为序列化的版本控制是一个非常有用的兼容手段,通常情况下,我们应该手工设置该值,idea或eclipse等IDE会有提示你设置其值。serialVersionUID可以任意设置,根据不同的兼容性做相应改动。

原创粉丝点击