Should serialVersionUID be unique for different classes? - java

class A implements Serializable{
private static final long serialVersionUID = 5L;
...
}
and
class B implements Serializable{
private static final long serialVersionUID = 6L;
...
}
then it is necessary to give unique serialVersionUID to both classes.
So can I assign serialVersionUID = 5L for both classes?
I read following links
Why generate long serialVersionUID instead of a simple 1L?
What is a serialVersionUID and why should I use it?

Yes, you can. Serial versions of different classes are independent and do not interfere each other.
PS
Eclipse even proposes you to set serialVersionID by default value that is 1L.

serialVersionUID is needed to remember versions of the class. It should be same while serializing and deserializing. It is a good programming practice to provide this value rather than JVM assigning one(generally it is hash). It is not necessary for two classes to have unique values.

serialVersionUID can be anything.
But the best practice is to start with the lowest number (for example 0L) and update it whenever you make a change in class which affects serialization, for example, adding/updating/removing a field, in which case you should increase the version number from 0L to 1L and so on.

SerialVersionUUID is an identifier used by a compiler to serialize/deserialize an object. This id is a private member to the class.
Creating new uuid for every serializable is good to have control over the serialization/deserialization process but it need NOT be unique among different classes.

Related

private static final long serialVersionUID = 1L; [duplicate]

This question already has answers here:
What is a serialVersionUID and why should I use it?
(25 answers)
Closed 7 months ago.
What is private static final long serialVersionUID = 1L in the below code?
public class Authenticator extends HttpServlet {
private static final long serialVersionUID = 1L;
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String username = request.getParameter("username");
String password = request.getParameter("mypassword");
if(authenticate(username, password)) {
HttpSession session = request.getSession();
session.setAttribute("username",username);
response.sendRedirect("product.jsp");
return;
}
else {
response.sendRedirect("index.jsp");
return;
}
}
}
First, few quick pointers regarding this.
It plays a role during serialization and deserialization. So for the classes e.g. MyCustomRuntimeException where you don't care about serialization, you could ignore it.
If you are using it on classes for serialization purposes but would not store them for any longer durations - more specifically if you would never create a backward incompatible version of that class during this storage, you would not need to change this.
For the use cases where you know you would permanently store it and would create new incompatible version, make sure to increment(uniquely change) it.
From java.io.Serializable
The serialization runtime associates with each serializable class a version number, called a serialVersionUID, which is used during deserialization to verify that the sender and receiver of a serialized object have loaded classes for that object that are compatible with respect to serialization. If the receiver has loaded a class for the object that has a different serialVersionUID than that of the corresponding sender's class, then deserialization will result in an InvalidClassException. A serializable class can declare its own serialVersionUID explicitly by declaring a field named "serialVersionUID" that must be static, final, and of type long:
ANY-ACCESS-MODIFIER static final long serialVersionUID = 42L;
If a serializable class does not explicitly declare a serialVersionUID, then the serialization runtime will calculate a default serialVersionUID value for that class based on various aspects of the class, as described in the Java(TM) Object Serialization Specification. However, it is strongly recommended that all serializable classes explicitly declare serialVersionUID values, since the default serialVersionUID computation is highly sensitive to class details that may vary depending on compiler implementations, and can thus result in unexpected InvalidClassExceptions during deserialization. Therefore, to guarantee a consistent serialVersionUID value across different java compiler implementations, a serializable class must declare an explicit serialVersionUID value. It is also strongly advised that explicit serialVersionUID declarations use the private modifier where possible, since such declarations apply only to the immediately declaring class--serialVersionUID fields are not useful as inherited members. Array classes cannot declare an explicit serialVersionUID, so they always have the default computed value, but the requirement for matching serialVersionUID values is waived for array classes.
From Joshua Bloch in Effective Java
the automatically generated UID is generated based on a class name, implemented interfaces, and all public and protected members. Changing any of these in any way will change the serialVersionUID. However, it is strongly recommended that all serializable classes explicitly declare serialVersionUID values, since the default serialVersionUID computation is highly sensitive to class details that may vary depending on compiler implementations and can produce different serialVersionUID in different environments. This can result in unexpected InvalidClassException during deserialization. Therefore, to guarantee a consistent serialVersionUID value across different java compiler implementations, a serializable class must declare an explicit serialVersionUID value. It is also strongly advised that explicit serialVersionUID declarations use the private modifier in serialVersionUID where possible, since such declarations apply only to the immediately declaring class.

Can Java Serialization UID numbering start at 1

The vast majority of examples of a Java serialVersionUID I have seen has a very long long value - see for example here where the given example is static final long serialVersionUID = 10275539472837495L or even the documentation which gives an example of static final long serialVersionUID = 42L
Is there any reason, though, that I can't call the first version of my class(es) static final long serialVersionUID = 1L the second 2L and so on? It compliles, serialises and deserialises fine but I was wondering if there were deeper reasons that made it not best practice.
From the Serializable Interface Docs:
If a serializable class does not explicitly declare a serialVersionUID, then the serialization runtime will calculate a default serialVersionUID value for that class based on various aspects of the class, as described in the Java(TM) Object Serialization Specification. However, it is strongly recommended that all serializable classes explicitly declare serialVersionUID values, since the default serialVersionUID computation is highly sensitive to class details that may vary depending on compiler implementations, and can thus result in unexpected InvalidClassExceptions during deserialization.
When you see a serialVersionUID such as 10275539472837495L, it is most probable one that was generated by the serialization runtime.
So, why would you explicitly set the serialVersionUID to one generated by the runtime? Suppose you forgot to set the serialVersionUID to a specific value such as 1L, and you serialized a class. After a while, you make some changes to the class implementing the Serializable interface and all out of sudden, an InvalidClassException is thrown because the generated serialVersionUIDs do not match anymore. To fix this, you can explicitly set the serialVersionUID to that generated with the previous version. This is pretty much how one might end up with these long serialVersionUIDs.
To avoid this alltogether, it is recommended to explicitly declare serialVersionUID values, as stated in the docs.

Serialization of an Object of a class on 2 different JVMs in java

I have a class say Counter. I serialize Object of this class on JVM-1 in one machine & transfer the serialized Object as a network stream to another machine & deserialize there in JVM-2.
Will this Object get deserialized properly ?
Would there be any error/exception thrown in this case?
Assuming i have compiled the class on both JVMs.
I am assuming that there is no serial Version UID present in the classes
As long as you have the same code/jdk (though different jdks may work) running at both ends, serialization-deserialization would not be a problem.
if you have serialVersionUID in your class, serialize/deserialize will not be a problem, but if serialVersionUID is missing in your code, as you are compiling class with both JVM(I understand, .class file has same content but compiled with different JVMs) in that case, serialVersionUID is assigned by java, which won't be same, hence serialize/deserialize will not work.
So, add
private static final long serialVersionUID = -6903933977591709194L;
in case you haven't added, with any value, and compile as many times, rest assured, serialize/deserialize will work. :)
The serialization runtime associates with each serializable class a version number, called a serialVersionUID, which is used during deserialization to verify that the sender and receiver of a serialized object have loaded classes for that object that are compatible with respect to serialization. If the receiver has loaded a class for the object that has a different serialVersionUID than that of the corresponding sender's class, then deserialization will result in an InvalidClassException. A serializable class can declare its own serialVersionUID explicitly by declaring a field named "serialVersionUID" that must be static, final, and of type long:
ANY-ACCESS-MODIFIER static final long serialVersionUID = 11L;
If a serializable class does not explicitly declare a serialVersionUID, then the serialization runtime will calculate a default serialVersionUID value for that class based on various aspects of the class, as described in the Java(TM) Object Serialization Specification. However, it is strongly recommended that all serializable classes explicitly declare serialVersionUID values, since the default serialVersionUID computation is highly sensitive to class details that may vary depending on compiler implementations, and can thus result in unexpected InvalidClassExceptions during deserialization. Therefore, to guarantee a consistent serialVersionUID value across different java compiler implementations, a serializable class must declare an explicit serialVersionUID value. It is also strongly advised that explicit serialVersionUID declarations use the private modifier where possible, since such declarations apply only to the immediately declaring class--serialVersionUID fields are not useful as inherited members. Array classes cannot declare an explicit serialVersionUID, so they always have the default computed value, but the requirement for matching serialVersionUID values is waived for array classes.
If the receiver has loaded a class for the object that has a different serialVersionUID than that of the corresponding sender's class, then deserialization will result in an InvalidClassException. A serializable class can declare its own serialVersionUID explicitly by declaring a field named "serialVersionUID" that must be static, final, and of type long

What does the "declare a static final serialVersionUID" warning mean and how to fix? [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
What does it mean: The serializable class does not declare a static final serialVersionUID field?
Java compiler warning: The serializable class [*****] does not declare a static final serialVersionUID field of type long.
Why? How to fix it?
This is explained fairly well here:
The serialVersionUID is a universal version identifier for a Serializable class. Deserialization uses this number to ensure that a loaded class corresponds exactly to a serialized object. If no match is found, then an InvalidClassException is thrown.
You fix the error by adding
private static final long serialVersionUID = 7526472295622776147L; // unique id
to the class.
Further reading:
java.io.Serializable
Why should I bother about serialVersionUID? (stackoverflow)
A side note: If you're using Eclipse and if you (and no one else) ever plan to serialize your classes, you can also suppress the error by going to
Window → Preferences → Java → Compiler → Errors/Warnings
and select "Ignore" on "Serializable Class without serialVersionUID".
just add
private static final long serialVersionUID = 1L;//or some long
Docs describe it pretty well
The serialization runtime associates
with each serializable class a version
number, called a serialVersionUID,
which is used during deserialization
to verify that the sender and receiver
of a serialized object have loaded
classes for that object that are
compatible with respect to
serialization. If the receiver has
loaded a class for the object that has
a different serialVersionUID than that
of the corresponding sender's class,
then deserialization will result in an
InvalidClassException. A serializable
class can declare its own
serialVersionUID explicitly by
declaring a field named
"serialVersionUID" that must be
static, final, and of type long:
ANY-ACCESS-MODIFIER static final long serialVersionUID = 42L;
If a
serializable class does not explicitly
declare a serialVersionUID, then the
serialization runtime will calculate a
default serialVersionUID value for
that class based on various aspects of
the class, as described in the
Java(TM) Object Serialization
Specification. However, it is strongly
recommended that all serializable
classes explicitly declare
serialVersionUID values, since the
default serialVersionUID computation
is highly sensitive to class details
that may vary depending on compiler
implementations, and can thus result
in unexpected InvalidClassExceptions
during deserialization. Therefore, to
guarantee a consistent
serialVersionUID value across
different java compiler
implementations, a serializable class
must declare an explicit
serialVersionUID value. It is also
strongly advised that explicit
serialVersionUID declarations use the
private modifier where possible, since
such declarations apply only to the
immediately declaring
class--serialVersionUID fields are not
useful as inherited members.
Also See
why-should-i-bother-about-serialversionuid
Declare it like that:
private static final long serialVersionUID = -4673040337179571462L;
Its required by serializable interface.
Are you extending a Swing object?
I often use the #suppressWarnings annotation to rid myself of this warning.
I guess the question of surpressing the warning or supplying a unique ID depends on the scale of your application and your intended use of Object serialisation.

Serialisation and sub-classes

If I define a class as Serialiable then when I create a sub-class it asks me to define a serialVersionUID. Is this necessary or can I rely on the one in the super-class?
I used to declare once SerialVersionUID in separate (possibly top class), like:
public static final long GlobalSerialVersionUID=0L;
And then in each Serializable class declare:
private static final long serialVersionUID = MyTopClass.GlobalSerialVersionUID;
this approach would guarantee that you will all time have the same SerialVersionUID and if you will be going to implement data interchange between different serialized versions - you could branch code between different serialized versions.
SerialVersionUID is used if you change the implementation of a class, but still want to be able to serialize/deserialise objects saved in the "old" format. So this means that you have to implement it in the subclass as well, if you want to change the subclass but not the superclass. However, if you dont need this "version control" you dont have to use SerialVersionUID at all.

Categories