IO流-序列化与反序列化详解

序列化:将对象转化为字节的过程称为序列化;
反序列化:将字节转化为对象的过程称为反序列化;
序列化的应用场景:
  • 数据在网络上传输也需要序列化;
  • 对象存储到本地磁盘上需要序列化;

transient:序列化中使用的关键字

被transient修饰的属性不进行序列化,反序列化时==>基本类型初始化为0,其它类型初始化为null

使用transient关键字的作用:
  • 网络数据传输中,敏感数据不进行传输;
  • 提高序列化效率;

serialVersionUID(串行化版本统一标识符)作用:

serialVersionUID用来表明类的不同版本间的兼容性。

生成方式:
  • 一种是默认的1L;
  • 另一种是根据类名,接口名,成员方法及属性等来生成一个64为的hash字段;
  • UID的默认值依赖于java编译器,对于同一个类,不同编译器编译可能导致UID不同;
显示定义UID的作用:
  • 确保不同版本有不同的UID;
  • 序列化一个类的实例,更改一个字段或者添加一个字段,不设置UID,任何更改会导致无法序列化实例,并抛出异常,如果添加UID,反序列化旧的实例,新增加或者更改的字段会被设为初始值,对象为null;

用ArrayList来分析系列化和反序列化:

ArrayList中的writeObject()和ReaderObject()参与了序列化和反序列化;

以写为例:如果不写writeObject(),就会默认调用ObjectOutputStream类下面的defaultwriteObject

为什么ArrayList中元素数组设置为transient:

ArrayList实际上是一个动态数组,每次在放满以后自动增长设定的长度值,如果数组自动增长长度设为100,但是实际上只放了一个元素,那么就会序列化99个null元素,为了保证在序列化的时候不会将这么多null同时进行序列化,所以把元素数组设置为transient;

ArrayList为什么要重写writeObject和readObject:

前面说过,为了防止一个包含大量空对象的数组被序列化,为了优化存储,所以ArrayList使用transient来声明elementData,但是作为集合,在序列化过程中还必须保证其中的元素可以被持久化下来,所以重写writeObject和readObject方法把其中的元素保留下来;

  • writeObject方法把elementData数组中的元素遍历保存到输出流(ObjectOutputStream)中;
  • readObject方法从输出流(ObjectInputStream)中读出对象并保存赋值到elementData数组中。

如何自定义序列化和反序列化策略:

可以通过在被序列化的类中增加writeObject和readObject方法;那么问题来了,虽然ArrayList中写了writeObject和readObject方法,但是这两个方法并没有被显示的调用;

如果一个类中包含writeObject和readObject方法,那么这两个方法如何被调用的:

在使用ObjectOutputStream的writeObject方法和ObjectInputStream的readObject方法时,会通过反射的方式调用;

Serializable明明是一个空的接口,他是怎么保证只有只有实现了改接口的方法才能进行序列化和反序列化:

这个问题的回答,我们回到ObjectOutputStream的writeObject的调用栈:
writeObject–》writeObject0–》writeOrdinaryObject–》writeSerialData–》invokeWriteObject
在进行序列化操作时,会判断要被序列化的类是否是String,Enum,Array和Serializable类型,如果不是则会直接抛出NotSerializableException异常。

类静态成员能否被序列化:

静态成员属于类级别的,所以不能序列化,这里的不能序列化的意思,是序列化信息中不包含这个静态成员域
而我们平时测试有时会发现静态成员会参加序列化,是因为你都在同一个机器(而且是同一个进程),因为你这个jvm已经把count加载进来了,所以你获取的是加载好的count,如果你是传到另一台机器或者你关掉程序重写写个程序读入test.obj,此时因为别的机器或新的进程是重新加载count的,所以count信息就是初始时的信息。

java =》IO流中一般通过ObjectInputStreamObjectOutputStream来序列化对象的,请点击此篇博客查看具体序列化过程:ObjectOutputStream/ObjectInputStream(对象输入/输出流)应用

你可能感兴趣的:(笔记,IO流)