在Java中实现Serializable接口时,我需要创建一个静态的final long serialVersionUID。我怎样才能创建自己的接口,为实现它的任何类创建此义务?
比如说
public class myStuff implements Serializable{
// required to get rid of warning
private static final long serialVersionUID = -403570729449249706L;
}
但我不知道如何将此功能添加到我自己的界面?
2条答案
按热度按时间py49o6xq1#
在这个问题上有很多误解。
在Java中实现Serializable接口时,我需要创建一个staic final long serialVersionUID。
不你不知道试试吧--写一个类,把
implements Serializable
粘在上面,* 不要 * 添加那个serialVersionUID
,然后用vanilla javac编译它。你会发现[A]编译得很好,[B]也不会生成警告。各种linter工具(添加额外代码清洁检查的工具)错误地抱怨必须添加该字段。有些时候,该字段是必需的,但在网络上,你通常不应该添加它。
这个字段是干什么的?
该字段出现的唯一情况是,如果您试图使用类的版本A进行序列化,然后在版本B位于类路径上时将其反序列化。(B与A不一样,事实上,不同到它们有不同的签名)。
这是非常棘手的-当Person类曾经有
String name
,现在有了PersonName name
,这意味着什么,因为name现在被拆分为首字母,合作伙伴名称,昵称等?你不能只是添加一些serialVersionUID
,然后祈祷java序列化机制知道该怎么做。正因为如此,序列化机制默认情况下将直接拒绝反序列化到已更改的类中(它更改了签名:字段或方法被添加/移除、或现有方法/字段被重命名、或字段的擦除类型已被改变、或方法获得/丢失参数、或其参数的擦除类型之一已被改变)。
这是正确的-几乎总是你不能“只是”反序列化成一个改变的版本,几乎总是你需要手动注意(使用
readObject
等机制来控制序列化机制)。设置
serialVersionUID
是向java反序列化机制指示的机制:实际上,只是反序列化到这个新版本;将任何新引入的字段保留为null / 0 / '\0' / false
-并忽略新版本中不再存在的旧字段的任何值。不需要字段
所有类都有一个serialVersionUID,无论您是否有该字段。具有显式sVU字段的类将其作为sVU,其他类具有其计算的sVU。您可以使用
serialver
工具查看这些内容,该工具就在java
和javac
可执行文件旁边。正确的方法
如果(极不可能!)你需要在两个不同的版本之间进行序列化/反序列化,和(更不可能!)你可以让反序列化器尽最大努力,然后写一些测试代码来确认这一点(毕竟,如果失败了,你的应用程序就会崩溃),这意味着你必须仍然拥有类的旧版本。所以,只要
serialver
它,并坚持串行版本到您的新版本。这是一个类应该拥有
serialVersionUID
字段的唯一情况。更多问题即将出现
Java的序列化机制不是特别好。它的API充满了奇怪的结构类型(除了
main
和agentmain
之外,java中没有其他东西可以做到这一点),并且除了JVM之外,任何东西都无法读取该格式。在这个微服务和网络连接的现代世界中,这是非常有限的。因此,序列化(就像java的烘焙一样)是不推荐的。甚至OpenJDK团队本身也倾向于淡化它或直接建议反对它。相反,序列化为JSON或使用protobuf。这些格式在许多平台上都是可读的,并且使序列化行为显式化。
修复linter
不管是什么告诉你'哦不!你有一个实现Serializable的类(通常不是故意的,例如
Exception
实现了它,因此所有的子类型都实现了它,但你很少序列化异常),你必须添加一个serialVersionUID字段!- 修好它,关掉警报别管这些了,我只想强制实现者有一些字段
这在Java中是不可能的。一个接口不能请求一个子类有一个字段,
static
成员不以任何方式“做”层次结构,你不能覆盖字段。从多种基础到Java语言的方式来看,“强制子类型添加字段”的概念完全是无稽之谈。这不仅仅是“不可能”,甚至没有意义。ajsxfq5m2#
根据Serializable的实现,它应该是每个类唯一的,这就是为什么它被设计成这样,所以不能在子类或多个类中重用相同的它