序列化是一种用来处理对象流的机制,是将java对象转换为字节序列的过程
对象流:将对象转换为二进制流byte[],我们可以对二进制流进行读写操作,流数据也可以在网络中进行传输。
实现方式:
- 类实现Serializable接口(标记接口,只是一个单纯的标记而已,说明这个类是可以被序列化的)(不想序列化的字段可以用transient修饰)
- 实现Externalizable接口(是Serializable接口的子类,transient无效)
- 我们可以使用一个输出流(
FileOutputStream
构造一个ObjectOutputStream
对象)来承载序列化后的对象,并用ObjectOutputStream
对象的writeObject(Object obj)
方法可以将obj对象写出(存到磁盘中,保存起来了),想恢复的话可以使用输入流
虽然实现Externalizable接口能带来一定的性能提升,但由于实现ExternaLizable接口导致了编程复杂度的增加,所以大部分时候都是采用实现Serializable接口方式来实现序列化。
什么时候使用序列化?
- 对象序列化可以实现分布式对象
应用场景:RMI(远程方法调用),要利用对象序列化运行远程主机上的服务,就像在本地机上运行对象一样。
RPC的话应该就要序列化,远程调用还可以用json来传数据。。
- java对象序列化不仅保留一个对象的数据,而且递归保存对象引用的每个对象的数据
这样子就可以将整个对象层次写入字节流中,可以保存在文件中或在网络连接上传递数据。
- 此外序列化可以进行对象的“深复制’’,复制对象本身及引用的对象本身。序列化一个对象可能得到整个对象序列。
简而言之序列化作用:
对象、文件、数据有许多不同的格式,很难统一保存和传输,但是都序列化转成字节流后,就都是同样的形式了,可以使用通用的格式保存或传输。想恢复直接反序列化恢复即可, 这样对象还是对象,文件还是文件。
当两个JVM(进程)在进行远程通信时,彼此可以发送各种类型的数据。无论是何种类型的数据,都会以二进制序列的形式在网络上传送。发送方需要把这个Java对象转换为字节序列,才能在网络上传送;接收方则需要把字节序列再恢复为Java对象。
所有涉及到数据传输或者存储的类,严格意义上来说都要加上序列化ID,这也是一种良好的编程习惯
。
serialVersionUID
序列化的时候,常常会看到一个ID,即 serialVersionUID
序列化运行时使用一个称为 serialVersionUID 的版本号与每个可序列化类相关联,**该序列号在反序列化过程中用于验证序列化对象的发送者和接收者是否为该对象加载了与序列化兼容的类。**为它赋予明确的值。显式地定义serialVersionUID有两种用途:
在某些场合,希望类的不同版本对序列化兼容,因此需要确保类的不同版本具有相同的serialVersionUID;
在某些场合,不希望类的不同版本对序列化兼容,因此需要确保类的不同版本具有不同的serialVersionUID。
Tips: 一般人员的密码信息等属性需要标识不被序列化。防止网络传输被窃取,特别是web程序。
参考文章:https://blog.csdn.net/tree_ifconfig/article/details/82766587