java的序列化以及serialVersionUID 的作用是什么?
2026/7/23 16:55:21 网站建设 项目流程

怎么让一个 Java 对象变得可序列化?
要让一个Java对象可序列化,非常简单,只需要满足以下几个条件

1. 实现java.io.Serializable接口

这是一个标记接口(Marker Interface),里面没有任何方法需要实现。它的作用只是告诉JVM:这个类的对象是可以被序列化的。
2. 核心注意事项:

  • 成员变量也必须是可序列化的:如果User类中包含另一个自定义类Address的引用,那么Address类也必须实现Serializable接口,否则在序列化时会抛出NotSerializableException
  • transient关键字:如果某些敏感字段(如密码)或不需要保存的字段(如临时计算结果)不需要参与序列化,可以使用transient关键字修饰。
  • 静态变量(static)不会被序列化:因为静态变量属于类,而不属于具体的对象实例。
  • 父类的序列化:如果一个子类实现了Serializable,而父类没有,子类仍然可以序列化,但反序列化时,父类的无参构造函数会被调用以初始化父类的属性。因此,父类必须有一个无参构造函数

2.serialVersionUID 的作用是什么

serialVersionUID 是 Java 序列化机制中的一个版本控制号。它是一个 private static final long 类型的常量。它的核心作用是:确保序列化和反序列化过程中,类结构的一致性(兼容性)。在反序列化时,JVM 会把传进来的字节流中的 serialVersionUID 与本地相应实体类的 serialVersionUID 进行对比:

• 如果相同,说明两者的版本一致,可以成功进行反序列化。

• 如果不同,JVM 就会抛出 InvalidClassException 异常,拒绝反序列化。

应用场景:
当你把一个对象序列化保存到了硬盘上,过了一段时间,你修改了该类的代码(比如增加了一个新字段)。

• 如果你定义了固定的 serialVersionUID,Java 会尽最大努力帮你兼容(新字段会赋予默认值,旧字段正常恢复)。

• 如果你没有定义,或者改变了 serialVersionUID,Java 就会认为这是两个完全不同的类,直接报错。

3.如果不显式定义serialVersionUID会发生什么?

如果你在类中没有显式声明serialVersionUIDJava 运行时环境(JVM)会自动根据这个类的结构(类名、实现的接口、属性、方法等)计算出一个哈希值作为默认的serialVersionUID

这会带来以下严重的问题和隐患:

1. 极其容易导致InvalidClassException崩溃

只要你的类发生了一丁点修改(哪怕只是加了一个空格、修改了一个不相干的方法、或者改了一个属性的修饰符),编译器重新编译后计算出的默认serialVersionUID就会发生改变。

  • 后果:之前序列化保存到磁盘上的数据,在类修改后,将永远无法被反序列化回来
2. 平台和编译器移植性差(最致命的问题)

不同厂商的 JVM(如 Oracle HotSpot、IBM J9、OpenJDK)或者不同的编译器,其计算serialVersionUID的算法可能会有细微差别。

  • 后果:你在 A 机器(Windows 平台,使用 Oracle JDK)上序列化的对象,拿到 B 机器(Linux 平台,使用 OpenJDK)上反序列化时,即使类的源码完全一模一样,也可能会因为计算出的默认serialVersionUID不同而导致反序列化失败。想·

4.最佳实践

  • 如果你做的是兼容性修改(如新增一个字段),不要修改serialVersionUID
  • 如果你做的是非兼容性修改(如修改了字段类型,或者删除了核心字段),需要手动修改serialVersionUID,以防止旧数据反序列化时出现逻辑错误。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询