Serializable 与 serialVersionUID

Serializable

Serializable是一个空接口,没有什么具体内容,它的目的只是简单的标识一个类的对象可以被序列化。

什么情况下需要序列化:

  • 当你想把的内存中的对象写入到硬盘的时候;
  • 当你想用套接字在网络上传送对象的时候;
  • 当你想通过RMI传输对象的时候,比如说你的内存不够用了,那计算机就要将内存里面的一部分对象暂时的保存到硬盘中,等到要用的时候再读入到内存中,硬盘的那部分存储空间就是所谓的虚拟内存。在比如过你要将某个特定的对象保存到文件中,我隔几天在把它拿出来用,那么这时候就要实现Serializable接口;

serialVersionUID

提到 serialVersionUID 就不得不提到 ObjectOutputStream 与 ObjectInputStream ,因为仅当使用这两个流对象时serialVersionUID才会起作用。

简单来说,Java的序列化机制是通过类的serversionUID来验证版本一致性的。在反序列化时,JVM会将传来的字节流中的serialVersionUID与本地相应实体类的serialVersionUID进行比较,如果相同就认为是一致的,可以进行反序列化,否则就会出现序列化版本不一致的异常,即是InvalidCastException。


InvalidCastException 示例

serialVersionUID有三种常见的生成方案:

  1. 根据类名、接口名、成员方法及属性等来生成一个64位的哈希字段,比如:
    private static final long serialVersionUID = xxxL;
  2. 默认的1L,比如:private static final long serialVersionUID = 1L;
  3. 完全随机生成;

关于三种方案的解析:

  • 第一种方案:没有手动声明serialVersionUID时java的默认策略,serialVersionUID的默认值完全依赖于Java编译器的实现,对于同一个类,用不同的Java编译器编译,有可能会导致不同的serialVersionUID。
    通常如果Class文件(类名、方法名等)没有发生变化(增加空格、换行、增加注释等等),就算编译多次,servialVersionUID也不会变化的。

  • 第二种方案:当场景没有特殊要求时可以使用这种方案。

  • 第三种方案:通常是为了保证序列化安全,假设serialVersionUID很容易被猜到,那么其他人就很容易反序列化该对象得到对象中保存的信息。所以当使用场景涉及到安全问题时,我们尽量保证serialVersionUID随机。

如果不想让之前的版本参与当前版本的反序列化时可以通过改动serialVersionUID版本来实现。从而避免不同版本间的反序列化混乱。(限于手动声明serialVersionUID的方案)

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容