从 Java 14 开始,@Serial 注释的用途是啥

Posted

技术标签:

【中文标题】从 Java 14 开始,@Serial 注释的用途是啥【英文标题】:What is the use of @Serial annotation as of Java 14从 Java 14 开始,@Serial 注释的用途是什么 【发布时间】:2020-12-26 05:22:05 【问题描述】:

Java 14 在java.io 包中引入了一个新的注解@Serial。 API 文档中的简要说明:

表示带注释的字段或方法是Java 对象序列化规范定义的serialization mechanism 的一部分。

据我了解,注释用于编译时验证(类似于@Override)以检查serialization mechanism 方法和字段是否使用正确。我不明白的是,只要注释是序列化机制的部分,它会影响反序列化本身吗?还是按照this comment 建议的方式改进反序列化功能设计的第一步?

因此,如果它应该是整个图片,请将它们全部添加:@Serializable、@NotSerializable、@Transient 并弃用 Serializable...

我对它的使用感到困惑,我还没有找到任何使用它的代码。您能否提供一个示例代码来突出显示未使用但应该使用注释时的问题?

【问题讨论】:

【参考方案1】:

我不明白的是,注释会影响 反序列化本身

没有。它的保留是“源”,因此在编译后被丢弃。字节码将不包含任何痕迹。它无法影响运行时行为(除了可能不会发生的编译时代码生成之外)。

@Override 一样,它是可选的,应该为可能在运行时才被发现的问题提供一些编译时保证。

例如,拼写错误serialVersionUID

@Serial
private static final long seralVersionUID = 123L; // compile-time error, should be 'serialVersionUID'

或者错误的访问修饰符

// compile-time error, must be private 
@Serial
public void writeObject(java.io.ObjectOutputStream out) throws IOException

基本上,带有注释的内容必须与 JavaDoc 中提到的 7 个适用元素(5 个方法,2 个字段)的描述完全匹配。如果方法的签名不匹配,或者修饰符错误,您将在运行时序列化失败之前发现问题。

【讨论】:

我明白了,静态场上的放置听起来很合理。但我不明白方法注释的目的(writeObjectreadObject 等...)。为什么 Serializable 接口本身不提供从 Java 8 开始的 default 方法? @Nikolas 方法是私有的。如果您将默认方法添加到接口,它们将需要是公共的(就像所有接口方法一样)。现有的 Serializable 类会中断,因为它们会尝试为这些方法分配比接口规定的更弱的访问权限。他们并没有试图重新设计序列化机制。您的建议是一项更大的任务。他们只是试图添加一些编译时检查。【参考方案2】:

此注解的存在纯粹是为了进行更好的编译时类型检查。这类似于@Override 注释,它的存在纯粹是为了捕捉设计意图,以便人类和工具有更多的信息可以使用。 @Override 注释不会使方法声明成为另一个方法声明的覆盖——这是由语言基于比较方法和超类型中的方法之间的名称、签名和可访问性来处理的. @Override 所做的是断言“我认为这是一个覆盖,如果我弄错了,请以编译错误的形式告诉我。”并且它作为代码读者的通知,这个方法在这个类中并不新。

因为序列化使用了“神奇”的方法和字段名(readObject之类的方法不是任何接口的一部分,它们只是被序列化神奇地赋予了意义),并且确定是否神奇的工作很棘手(方法一定不能只有正确的名称和参数,但正确的可访问性和静态性),很容易声明一个您认为应该由序列化使用但序列化不同意的方法。

@Serial 注释让您可以做出类似的断言:您希望这是那些神奇的序列化成员(字段和方法)之一,如果它与配置文件不匹配,编译器应该提醒您一个错误。并且它向读者提供了类似的提示,该成员将被序列化使用。

对于应用程序和域代码,大多数开发人员可能不会为此烦恼。但库作者可能会发现它有助于增强类型检查和更好地捕捉设计意图。

【讨论】:

从 JDK 17 开始,javac 不检查 @Serial 注释。 mail.openjdk.java.net/pipermail/core-libs-dev/2021-September/…

以上是关于从 Java 14 开始,@Serial 注释的用途是啥的主要内容,如果未能解决你的问题,请参考以下文章

C++从0到14.程序的注释

USB-Serial 在新的 linux(内核 4.12.14)中立即失去连接

usb2.0-serial串口驱动在此!!!需要的速来

Java基础语法

Java代码注释

python笔记3:注释命名风格