31

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

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

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

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

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

4

2 回答 2

23

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

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

就像@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 个字段)的描述完全匹配。如果方法的签名不匹配,或者修饰符错误,您将在运行时序列化失败之前发现问题。

于 2020-09-07T20:04:57.890 回答
22

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

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

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

大多数开发人员可能不会为应用程序和域代码而烦恼。但是库作者可能会发现它作为一种参与更强大的类型检查和更好地捕捉设计意图的方法很有用。

于 2020-09-08T14:04:09.383 回答