zoukankan      html  css  js  c++  java
  • 关于Serializable的serialVersionUID

    serialVersionUID作用:序列化时为了保持版本的兼容性,即在版本升级时反序列化仍保持对象的唯一性。


    在实现了Serializable接口的class中,需要声明一个long serialVersionUID,用来标明当前class的版本号,但很多人在编程时,总是不原意去声明这个serialVersionUID,由JVM自己来生成。
    下面来看看serialVersionUID的作用:
    1、如果在序列化写时的版本号和序列化读时的版本号,不一致,将会有异常:
    java.io.InvalidClassException:local class incompatible: stream classdesc serialVersionUID = …, local class serialVersionUID = …

    2、那如果在class中不声明这个属性呢?那结果可以就会变得比较诡异了:
    1)、在序列化写的时候,虚拟机A会为它计算出一个serialVersionUID,计算的方法是依据class的信息,再具体我也不清楚了。
    2)、在序列化读的时候,虚拟机B也会为class计算出一个serialVersionUID,然后做比较。
    3)、那么如果两个虚拟机是不同类型的虚拟机,那么计算方法可能就不一样了,于是即使相同的class,serialVersionUID也可能会不同,不同的class的,理论上来说,也存在serialVersionUID相同的可能性,所以,serialVersionUID尽量由我们自己来指定,而不要由虚拟机来计算。

    3、那如果serialVersionUID一致,而class发生了变化呢?
    1)、如果虚拟机A中的AClass有一个属性,而虚拟机B中的AClass,没有这个属性,那么这个属性将被忽略,而不会有异常。
    2)、如果虚拟机A中的AClass没有的属性,而在虚拟机B中多出来的属性,那么这个属性将被赋予一个缺省值,而不会有异常。
    3)、如果虚拟机A中的AClass有一个属性,在虚拟机B中的AClass也有这个属性,但这个属性的类型变了,比如说int变成了long,抑或其他的变化,将会有异常:java.io.InvalidClassException:incompatible types for field …
    经过序列化而产生的异常都是 java.io.InvalidClassException,不会产生java.lang.ClassCastException,两者还是有比较大的区别的,从名字上就可以看得出来。
    看完你还会让JVM自己来生成serialVersionUID吗?你还加@SuppressWarnings("serial")吗?在一个单机上或许看不出什么问题,但在分布式计算、或者你需要提供jar供别人使用的时候,这个问题就会暴露。
  • 相关阅读:
    Mac OSX下增加TCP连接数
    Connection reset by peer的常见原因及解决办法
    修改主机名
    docker 查看 docker容器启动 完整命令
    nginx 日志打印响应时间 request_time 和 upstream_response_time
    Ubuntu16.04 安装 Docker
    VictoriaMetrics vmagent 使用
    VictoriaMetrics vmauth 使用
    VictoriaMetrics集群模式的一些说明
    promgen prometheus 配置文件生成工具
  • 原文地址:https://www.cnblogs.com/archermeng/p/7537220.html
Copyright © 2011-2022 走看看