从Java 14开始,@Serial注释有什么用

Java 14 在包中引入了一个新的注释@Serial。它在 API 文档中的简要描述:java.io

指示带注释的字段或方法是由 Java 对象序列化规范定义的序列化机制的一部分。

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

因此,如果它应该是整个画面,请将它们全部添加:@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个字段)。如果方法的签名不匹配,或者修饰符错误,您将在运行时序列化失败之前捕获问题。


答案 2

此注释的存在纯粹是为了更好地进行编译时类型检查。它以这种方式类似于注释,注释的存在纯粹是为了捕获设计意图,以便人员和工具具有更多信息。注释不会使方法声明成为另一个方法声明的重写 - 该方法由语言根据比较超类型中的方法和方法之间的名称,签名和可访问性来处理。所做的是断言“我认为这是一个覆盖,如果我错了,请以编译错误的形式告诉我。它向代码的读者发出通知,即此方法对于此类来说并不新鲜。@Override@Override@Override

由于序列化使用“magic”方法和字段名称(像这样的方法不是任何接口的一部分,它们只是通过序列化神奇地赋予了意义),并且确定魔术是否有效是棘手的(方法不仅必须具有正确的名称和参数,而且必须具有正确的可访问性和静态性),因此很容易声明一个您认为应该由序列化使用的方法, 但序列化不同意。readObject

注释允许您进行类似的断言:您打算这是那些神奇的序列化成员(字段和方法)之一,如果它与配置文件不匹配,编译器应提醒您一个错误。它向读者提供了类似的提示,即此成员将由序列化使用。@Serial

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