Java private static final long serialVersionUID 作用
对象序列化 Serializable
一般情况下我们序列化对象的时候需要 implements Serializable 接口,然后就可以序列化了。序列化 称呼为 对象存档 更合适。但是 经常会看到 private static final long serialVersionUID = ***L
这样一句话 ,
import java.io.Serializable;
class DeepClone implements Serializable{
private static final long serialVersionUID = 1L;
/**
* 利用序列化和反序列化进行对象的深拷贝
* @return
* @throws Exception
*/
public Object deepClone() throws Exception{
//序列化
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bos);
oos.writeObject(this);
//反序列化
ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
ObjectInputStream ois = new ObjectInputStream(bis);
return ois.readObject();
}
}
如果你不添加serialVersionUID,那么Eclipse在会根据这个类的结构(成员变量,成员变量的个数等),生成一个hash值,然后将这个值作为serialVersionUID。
外网结束SerialVersionUID
SerialVersionUID is an ID which is stamped on object when it get serialized usually hashcode of object, you can use tool serialver to see serialVersionUID of a serialized object . SerialVersionUID is used for version control of object. you can specify serialVersionUID in your class file also. Consequence of not specifying serialVersionUID is that when you add or modify any field in class then already serialized class will not be able to recover because serialVersionUID generated for new class and for old serialized object will be different. Java serialization process relies on correct serialVersionUID for recovering state of serialized object and throws java.io.InvalidClassException in case of serialVersionUID mismatch.
SerialVersionUID,后面简称SUID,是当对象序列化时候你对象对应代码的一个标识类似与对象跟代码之间的K-V ,SUID的值常为该对象的hascode。你可以使用工具serialver查看一个序列化对象的SUID。SUID用于控制对象的版本。你也可以在类文件中指定SUID。不指定SUID的结果就是当你添加或者更改类的域并已经序列化类的时候,类是不能再恢复了,因为新的SUID和之前的SUID不同了。Java的序列化过程依赖于正确的SUID来反序列化已经序列化的对象,如果SUID不匹配,那么就会抛 java.io.InvalidClassException 异常了。
An SUID is not a hash of the object, but a hash of its originating class. If the class is updated, for example with different fields, the SUID can change. You have four (at least) possible courses of action:-
1: Leave out the SUID. This tells the runtime that there are no differences between versions of classes when serialising and deserialising.
2: Always write a default SUID, which looks like the heading of this thread. That tells the JVM that all versions with this SUID count as the same version.
3: Copy an SUID from a previous version of the class. That tells the runtime that this version and the version the SUID came from are to be treated as the same version.
4: Use a generated SUID for each version of the class. If the SUID is different in a new version of the class, that tells the runtime that the two versions are different and serialised instances of the old class cannot be deserialised as instances of the new class.
UID不是一个对象的哈希值(翻译错了,公司一个牛逼同事提醒了!),是源类的哈希值。如果类更新,例如域的改变,SUID会变化,这里有4个步骤:
- 忽略SUID,相当于运行期间类的版本上的序列化和反序列上面没有差异。
- 写一个默认的SUID,这就好像线程头部。告诉JVM所有版本中有着同样SUID的都是同一个版本。
- 复制之前版本类的SUID。运行期间这个版本和之前版本是一样的版本。
- 使用类每个版本生成的SUID。如果SUID与新版本的类不同,那么运行期间两个版本是不同的,并且老版本类序列化后的实例并不可以反序列成新的类的实例,说白了如果我们对类中属性进行了增加修改或删除,那么此时SUID要变的,因为 序列化跟反序列化要保持一致。