实现Serializable接口的目的是为类可持久化,比如在网络传输或本地存储,为系统的分布和异构部署提供先决条件。
若没有序列化,现在我们所熟悉的远程调用,对象数据库都不可能存在,serialVersionUID适用于java序列化机制。
简单来说,JAVA序列化的机制是通过判断类的serialVersionUID来验证的版本一致的。
在进行反序列化时,JVM会把传来的字节流中的serialVersionUID于本地相应实体类的serialVersionUID进行比较。如果相同说明是一致的,可以进行反序列化,否则会出现反序列化版本一致的异常,即是InvalidCastException。
具体序列化的过程是这样的:序列化操作时会把系统当前类的serialVersionUID写入到序列化文件中,当反序列化时系统会自动检测文件中的serialVersionUID,判断它是否与当前类中的serialVersionUID一致。
如果一致说明序列化文件的版本与当前类的版本是一样的,可以反序列化成功,否则就失败;
serialVersionUID有两种显示的生成方式:
一是默认的1L,比如:private static final long serialVersionUID = 1L;
二是根据包名,类名,继承关系,非私有的方法和属性,以及参数,返回值等诸多因子计算得出的,极度复杂生成的一个64位的哈希字段。基本上计算出来的这个值是唯一的。
比如:private static final long serialVersionUID = xxxxL;
注意:显示声明serialVersionUID可以避免对象不一致,
当一个类实现类Serializable接口,如果没有显示定义serialVersionUIDEclipse会自动给出相应的提醒;面对这种情况,我们只需要在Eclipse中点击类的warning图标,Eclipse就会自动给出两种生成方式。
如果不想定义,在Eclipse的设置中也可以把它关掉的,设置如下:
Window ==> Preferences ==> Java ==> Compiler ==> Error/Warnings ==> Potential programming problems
将Serializable class without serialVersionUID的warning改成ignore即可。
如果Class文件(类名,方法明等)没有发生变化(增加空格,换行,增加注释等等),就算再编译多次,serialVersionUID也不会变化的。
下面用代码说明一下serialVersionUID在应用中常见的几种情况。
(1)序列化实体类
package com.example.demo.entity.serializable;
import java.io.Serializable;
public class Persion implements Serializable {
private static final long serialVersionUID = 4359709211352400087L;
public Long id;
public String name;
public final String userName;
public Persion(Long id, String name){
this.id = id;
this.name = name;
userName = "dddbbb";
}
public String toString() {
return id.toString() + "--" + name.toString();
}
}
(2)序列化功能:
package com.example.demo.entity.serializable;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
i