1.Serializable:
Serializable是java.io包中定义的、用于实现Java类的序列化操作而提供的一个语义级别的接口。
Serializable序列化接口没有任何方法或者字段,只是用于标识可序列化的语义。
实现了Serializable接口的类可以被ObjectOutputStream转换为字节流,同时也可以通过ObjectInputStream再将其解析为对象。
例如,我们可以将序列化对象写入文件后,再次从文件中读取它并反序列化成对象,也就是说,可以使用表示对象及其数据的类型信息和字节在内存中重新创建对象。
序列化:
是将对象状态转换为可保持或传输的格式的过程。与序列化相对的是反序列化,它将流转换为对象。这两个过程结合起来,可以轻松地存储和传输数据。
把对象转换为字节序列的过程称为对象的序列化,把字节序列恢复为对象的过程称为对象的反序列化。
那么什么情况下需要序列化呢?大概有这样两类比较常见的场景:
1)、需要把内存中的对象状态数据保存到一个文件或者数据库中的时候,这个场景是比较常见的,例如我们利用mybatis框架编写持久层insert对象数据到数据库中时;
2)、网络通信时需要用套接字在网络中传送对象时,如我们使用RPC协议进行网络通信时;
2.serialVersionUID:
对于JVM来说,要进行持久化的类必须要有一个标记,只有持有这个标记JVM才允许类创建的对象可以通过其IO系统转换为字节数据,从而实现持久化,而这个标记就是Serializable接口。而在反序列化的过程中则需要使用serialVersionUID来确定由那个类来加载这个对象,所以我们在实现Serializable接口的时候,一般还会要去尽量显示地定义serialVersionUID,如:
private static final long serialVersionUID = 1L;
在反序列化的过程中,如果接收方为对象加载了一个类,如果该对象的serialVersionUID与对应持久化时的类不同,那么反序列化的过程中将会导致InvalidClassException异常。例如,在之前反序列化的例子中,我们故意将User类的serialVersionUID改为2L,如:
private static final long serialVersionUID = 2L;
就会产生错误。
如果我们在序列化中没有显示地声明serialVersionUID,则序列化运行时将会根据该类的各个方面计算该类默认的serialVersionUID值。但是,Java官方强烈建议所有要序列化的类都显示地声明serialVersionUID字段,因为如果高度依赖于JVM默认生成serialVersionUID,可能会导致其与编译器的实现细节耦合。