What is the use of @Serial annotation as of Java 14
Asked Answered
P

2

54

Java 14 introduces a new annotation @Serial in the java.io package. Its brief description in the API docs:

Indicates that an annotated field or method is part of the serialization mechanism defined by the Java Object Serialization Specification.

As far as I understand the annotation is used for the compile-time validation (similarly to @Override) to check whether the serialization mechanism methods and fields are used correctly. What I don't understand, does the annotation affect the de/serialization itself as long as it is a part of the serialization mechanism? Or is it a first step to improve the de/serialization feature design in the way suggested with this comment?

So if it should be the whole picture, add them all: @Serializable, @NotSerializable, @Transient and make Serializable deprecated…

I am confused of its use and I haven't found any code using it. Would you provide a sample code highlighting the issues when the annotation is not used but should be?

Phenacaine answered 7/9, 2020 at 19:51 Comment(0)
C
33

This annotation exists purely to engage better compile-time type checking. It is analogous in this way to the @Override annotation, which exists purely to capture design intent, so that humans and tools have more information to work with. The @Override annotation does not make a method declaration an override of another -- that is handled by the language based on comparing names, signatures, and accessibility between the method and methods in the supertype(s). What @Override does is assert that "I think this is an override, if I am mistaken, please tell me in the form of a compilation error." And it serves as notice to readers of the code that this method is not new with this class.

Because serialization uses "magic" method and field names (methods like readObject are not part of any interface, they are just magically given significance by serialization), and the determination of whether the magic works is tricky (methods must not only have the right name and arguments, but the right accessibility and static-ness), it is easy to declare a method that you think is meant to be used by serialization, but for which serialization doesn't agree.

The @Serial annotation lets you make a similar kind of assertion: that you intend that this is one of those magic serialization members (fields and methods), and if it does not match the profile, the compiler should alert you with an error. And it provides a similar hint to readers that this member is going to be used by serialization.

Most developers probably won't bother with this for application and domain code. But library authors may find it useful as a way to engage stronger type checking and better capture design intent.

Cuirass answered 8/9, 2020 at 14:4 Comment(2)
As of JDK 17, javac does not check the @Serial annotation. mail.openjdk.java.net/pipermail/core-libs-dev/2021-September/…Carmarthenshire
Thanks for the link! I couldn't provoke a warning or error with JDK 18 either.Drawn
R
43

What I don't understand, does the annotation affect the de/serialization itself

No. Its retention is 'source', so it's discarded after compilation. The bytecode will contain no trace of it. It has no way to influence runtime behaviour (besides possibly compile-time code generation, which does not happen).

Like @Override, it is optional and is supposed to give some compile-time assurance for problems which might otherwise not be caught until runtime.

For example, misspelling serialVersionUID:

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

Or the wrong access modifier

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

Basically, something annotated with this must exactly match the descriptions of the 7 applicable elements mentioned in the JavaDoc (5 methods, 2 fields). If the signature of a method does not match, or the modifiers are wrong, you will catch the problem before serialization fails at runtime.

Reichert answered 7/9, 2020 at 20:4 Comment(2)
I see the point, the placement on the static field sounds reasonable. But I don't understand the purpose of the annotation for the methods (writeObject, readObject, etc...). Why the Serializable interface itself doesn't provide default methods as of Java 8?Phenacaine
@Nikolas The methods are private. If you added default methods to the interface, they would need to be public (as all interface methods are). Existing Serializable classes would break because they would be attempting to assign weaker access to those methods than is dictated by the interface. They are not attempting to the redesign the serialization mechanism. What you are suggesting is a much larger task. They are simply trying to add some compile-time checks.Reichert
C
33

This annotation exists purely to engage better compile-time type checking. It is analogous in this way to the @Override annotation, which exists purely to capture design intent, so that humans and tools have more information to work with. The @Override annotation does not make a method declaration an override of another -- that is handled by the language based on comparing names, signatures, and accessibility between the method and methods in the supertype(s). What @Override does is assert that "I think this is an override, if I am mistaken, please tell me in the form of a compilation error." And it serves as notice to readers of the code that this method is not new with this class.

Because serialization uses "magic" method and field names (methods like readObject are not part of any interface, they are just magically given significance by serialization), and the determination of whether the magic works is tricky (methods must not only have the right name and arguments, but the right accessibility and static-ness), it is easy to declare a method that you think is meant to be used by serialization, but for which serialization doesn't agree.

The @Serial annotation lets you make a similar kind of assertion: that you intend that this is one of those magic serialization members (fields and methods), and if it does not match the profile, the compiler should alert you with an error. And it provides a similar hint to readers that this member is going to be used by serialization.

Most developers probably won't bother with this for application and domain code. But library authors may find it useful as a way to engage stronger type checking and better capture design intent.

Cuirass answered 8/9, 2020 at 14:4 Comment(2)
As of JDK 17, javac does not check the @Serial annotation. mail.openjdk.java.net/pipermail/core-libs-dev/2021-September/…Carmarthenshire
Thanks for the link! I couldn't provoke a warning or error with JDK 18 either.Drawn

© 2022 - 2024 — McMap. All rights reserved.