首先,如果对象需要网络传输或者持久化(我的理解是dto和entity/model),那么就需要实现Serializable接口。为了防止反序列失败,该对象需提供一个默认的serialVersionUID(该值在反序列化的时候会进行校验,
如果校验失败会抛异常-InvalidClassException)。

但如果只是转换为json字符串的形式与网络打交道(比如MVC中前后端分离情况下,返回json-response给前端),那么这个response对象就不需要实现Serializable接口。

关于UID

  • serialVersionUID有两种显式的生成方式

    1
    2
    一个是默认的1L
    一个是根据类名、接口名、成员方法及属性等来生成一个64位的哈希字段,
  • 如果没有显式地定义一个名为serialVersionUID的long型的变量,编译器在编译的时候也会根据类名、接口名、成员方法及属性等来生成一个64位的哈希字段,这就决定了这个类在序列化上一定不是向前兼容的

  • 使用默认计算的serialVersionUID就会有一个明显的劣势

    1
    2
    3
    4
    使用默认计算的serialVersionUID就会有一个明显的劣势,那就是类一旦序列化后,
    我们就不能修改该类了,因为计算的serialVersionUID会改变,导致后期反序列话失败。
    为了避免以上情况,我们手动定义一个静态常量来人为定义serialVersionUID,因为一旦手动定义了,
    虚拟机就不会再进行计算了
  • 通常关于序列相关的代码,最常遇到的bug就是InvalidClassException,大概率就是因为没有显示声明UID,导致反序列化报错

总结

1
2
1. entity/model和dto必须实现Serializable
2. 一旦实现Serializable,必须显示声明UID