Serializable
Serializable是一个空接口,没有什么具体内容,它的目的只是简单的标识一个类的对象可以被序列化。
什么情况下需要序列化:
- 当你想把的内存中的对象写入到硬盘的时候;
- 当你想用套接字在网络上传送对象的时候;
- 当你想通过RMI传输对象的时候,比如说你的内存不够用了,那计算机就要将内存里面的一部分对象暂时的保存到硬盘中,等到要用的时候再读入到内存中,硬盘的那部分存储空间就是所谓的虚拟内存。在比如过你要将某个特定的对象保存到文件中,我隔几天在把它拿出来用,那么这时候就要实现Serializable接口;
serialVersionUID
提到 serialVersionUID 就不得不提到 ObjectOutputStream 与 ObjectInputStream ,因为仅当使用这两个流对象时serialVersionUID才会起作用。
简单来说,Java的序列化机制是通过类的serversionUID来验证版本一致性的。在反序列化时,JVM会将传来的字节流中的serialVersionUID与本地相应实体类的serialVersionUID进行比较,如果相同就认为是一致的,可以进行反序列化,否则就会出现序列化版本不一致的异常,即是InvalidCastException。
serialVersionUID有三种常见的生成方案:
- 根据类名、接口名、成员方法及属性等来生成一个64位的哈希字段,比如:
private static final long serialVersionUID = xxxL; - 默认的1L,比如:private static final long serialVersionUID = 1L;
- 完全随机生成;
关于三种方案的解析:
第一种方案:没有手动声明serialVersionUID时java的默认策略,serialVersionUID的默认值完全依赖于Java编译器的实现,对于同一个类,用不同的Java编译器编译,有可能会导致不同的serialVersionUID。
通常如果Class文件(类名、方法名等)没有发生变化(增加空格、换行、增加注释等等),就算编译多次,servialVersionUID也不会变化的。第二种方案:当场景没有特殊要求时可以使用这种方案。
第三种方案:通常是为了保证序列化安全,假设serialVersionUID很容易被猜到,那么其他人就很容易反序列化该对象得到对象中保存的信息。所以当使用场景涉及到安全问题时,我们尽量保证serialVersionUID随机。
如果不想让之前的版本参与当前版本的反序列化时可以通过改动serialVersionUID版本来实现。从而避免不同版本间的反序列化混乱。(限于手动声明serialVersionUID的方案)