在Java中实现Serializable接口时,我需要创建一个静态的最终长序列版本UID.我如何创建自己的接口,为实现它的任何类创建此义务?

例如,

public class myStuff implements Serializable{
    // required to get rid of warning 
    private static final long serialVersionUID = -403570729449249706L;
}

但我想不出如何将此功能添加到我自己的界面中?

推荐答案

在这个问题上有一堆误解.

在Java中实现Serializable接口时,我需要创建一个静态的最终长序列版本UID.

不,你不知道.试一试--go 编写一个类,在上面加上implements Serializable,do not加上serialVersionUID,然后用普通的javac编译它.您会发现[A]编译得很好,[B]也不会生成任何警告.

各种LinterTool(添加额外代码清洁度判断的工具)错误地抱怨必须添加该字段.有时该字段是必需的,但在网络上通常不应该添加它.

那块地到底是做什么用的?

只有当您try 使用类的版本A进行序列化,然后在版本B位于类路径上时将其反序列化时,该字段才会出现.(B与A不同,事实上,B与A的签名非常不同).

This is extremely tricky-当Person类以前有String name个,现在有PersonName name个,因为名字现在被分成首字母、合作伙伴名称、昵称等,这意味着什么?您不能只添加一些serialVersionUID,然后祈祷Java序列化机制知道该做什么.

正因为如此,默认情况下,序列化机制将完全拒绝反序列化为已更改的类(它更改了签名:添加/移除了一个字段或方法,或重命名了现有的方法/字段,或更改了字段的擦除类型,或更改了方法获得/丢失的参数,或其参数之一的擦除类型已更改).

This is correct--几乎总是不能‘只是’反序列化成一个像那样改变的版本,而且几乎总是需要手动注意(使用readObject和类似的机制来控制序列化机制).

设置serialVersionUID是向Java反序列化机制指示的机制:实际上,只需反序列化到这个新版本;将任何新引入的字段保留为null / 0 / '\0' / false-并忽略新版本中不再存在的旧字段的任何值.

不需要这块地

所有类都有一个序列版本UID,无论您是否有该字段.具有显式SVU字段的类将其视为SVU,而其他类具有其计算出的SVU.您可以使用javajavac可执行文件旁边的serialver工具轻松地看到这些.

做这件事的正确方法

If(极不可能!)你需要在两个不同的版本之间进行序列化/反序列化,and(更不可能!)你可以通过让反序列化程序尽最大努力而"逍遥法外",然后是write some test code that confirms this(毕竟,如果失败,你的应用程序将被 destruct ),这意味着你必须仍然拥有旧版本的类.所以,只需serialver个,然后将这个连续版本粘贴到新版本中.

That is the one and only circumstance a class should EVER have a 100 field.

地平线上将出现更多问题

Java的串行化机制并不是特别好.它的API充满了奇怪的 struct 化类型(除了mainagentmain之外,在Java中没有其他语言可以做到这一点),并且除了JVM之外,其他任何人都无法读取该格式.在这个微服务和网络连接的现代世界里,这是非常有限的.因此,序列化(如在Java中烘焙的东西)是not recommended.即使是OpenJDK团队本身也倾向于淡化它,或者直接建议不要使用它.

相反,可以将其序列化为JSON或使用protobuf.这些格式在许多平台上都是可读的,并且使序列化行为变得明确.

修好你的短绒布

不管是什么告诉你‘哦,不!你有一个实现了Serializable的类(通常,不是故意的,比如Exception实现了它,因此所有的子类型都实现了,但是你很少序列化异常),你必须添加一个SerialVersionUID字段!-修复它.关闭那个警告.

不管这些,我只想强迫实现者有一些域

这在Java中几乎是不可能的.接口cannot要求一个子类有一个字段,static个成员不以任何方式‘做’层次 struct ,并且您不能重写字段.在多种从基础到Java语言的方法中,‘强制使用子类型来添加字段’的概念是完全没有意义的.这不仅仅是"不可能",它甚至没有任何意义.

Java相关问答推荐

无法从TemporalAccessor获取Instant:{},ISO解析为2024-04- 25 T14:32:42类型为java.time. form.Parsed

Gmail Javi API批量处理太多请求

那么比较似乎不是词典学的,尽管doctor 这么说

为什么我的画布没有显示在PFA应用程序中?

了解Android Studio中的调试器输出

Java模式匹配记录

无法传递消费者<;>;实例

为什么Java的代码工作(if condition内部的实例)

Character::Emoji不支持带数字的字符吗?

确定Java中Math.Ranb()输出的上限

为什么我的在一个范围内寻找素数的程序不能像S所期望的那样工作

使用GridBagLayout正确渲染

什么是Java原子属性的正确getter和setter

生成桥方法以解决具有相同擦除的冲突方法

是否有一个Java Future实现可以在池繁忙时在调用者线程中执行?

Spring Validator批注不起作用

在单例类上获取Java锁,了解原因

rest api服务 spring 启动中出现IllegalFormatConversionException

错误:JOIN/ON的参数必须是boolean类型,而不是bigint类型.Java Spring启动应用程序

为什么Java编译器为没有参数的方法(getter方法)创建桥接方法