private static final long serialVersionUID的作用

来源:互联网 发布:诸神黄昏灵羽进阶数据 编辑:程序博客网 时间:2024/04/28 21:12

原文

今天在看项目源码的时候发现struts的action里面有

[java] view plaincopy在CODE上查看代码片派生到我的代码片
  1. private static final long serialVersionUID = -1672970955045193907L;  
这样的一条语句。

中文搜索之后,全部都是

如果你修改了此类, 要修改此值。否则以前用老版本的类序列化的类恢复时会出错。为了在反序列化时,确保类版本的兼容性,最好在每个要序列化的类中加入private static final long serialVersionUID这个属性,具体数值自己定义。


中文的全部都是抄来抄去的答案。这真是叫人恶心。


有趣的事,在外国网站也出现了这样的状况。原帖:http://www.coderanch.com/t/596397/java/java/private-static-final-long-serialVersionUID


What is private static final long serialVersionUID = 1L; ???
上面那句话是什么?


Hi Friends, 

Can you please tell me the purpose of this line ???

朋友们,

谁能告诉我这段代码的缘由?


     
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,是当对象序列化的时候对象的一个标识(stamp on 在这里我也不太清楚翻译成什么好),SUID的值常为该对象的hascode。你可以使用工具serialver查看一个序列化对象的SUID。SUID用于控制对象的版本。你也可以在类文件中指定SUID。不指定SUID的结果就是当你添加或者更改类的域并已经序列化类的时候,类是不能再恢复了,因为新的SUID和之前的SUID不同了。Java的序列化过程依赖于正确的SUID来反序列化已经序列化的对象,如果SUID不匹配,那么就会抛 java.io.InvalidClassException 异常了。


Please don’t simply copy and paste from another website; that may be breach of copyright. That quote is confusing at the best.

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.


    请不用简单地从别的网站复制粘贴(一针见血指出上面回答的缺点);这是对版权的破坏,而且这样的描述最多还是困惑读者。

    SUID不是一个对象的哈希值(翻译错了,公司一个牛逼同事提醒了!),是源类的哈希值。如果类更新,例如域的改变,SUID会变化,这里有4个步骤:

    1.忽略SUID,相当于运行期间类的版本上的序列化和反序列上面没有差异。

    2.写一个默认的SUID,这就好像线程头部。告诉JVM所有版本中有着同样SUID的都是同一个版本。

    3.复制之前版本类的SUID。运行期间这个版本和之前版本是一样的版本。

    4.使用类每个版本生成的SUID。如果SUID与新版本的类不同,那么运行期间两个版本是不同的,并且老版本类序列化后的实例并不可以反序列成新的类的实例。


    第四点才是private static final long serialVersionUID的作用的重点所在。


    Thanks Campbell, will be careful from now on. 

    后面那个直接抄答案的跟上面那位答者致谢。对方也在后面的回复中也竖起大拇指。


    最后总结一下:其实序列化的作用是能转化成Byte流,然后又能反序列化成原始的类。能在网络进行传输,也可以保存在磁盘中,有了SUID之后,那么如果序列化的类已经保存了在本地中,中途你更改了类后,SUID变了,那么反序列化的时候就不会变成原始的类了,还会抛异常,主要就是用于版本控制。


    这完完全全是和国内这种复制粘贴漫天飞的问答的不同的格调,这正是技术所需要的一种气氛,一种对更好的答案的追求。

    希望以后国内的技术氛围也能如此!

  • 0 0