About generating serialVersionUID using Eclipse 3.1

S

Sameer

I am using Eclipse 3.1.
I have created a class which extends Frame and do not implement the
Serializable interface as in the declaration of class.
But still the IDE is giving the warning:
The serializable class 'AnyClass' does not declare a static final
serialVersionUID field of type long.
This is happening with most of the classes.
Using QuickFix to generate serialVersionUID for each class does not
seem to be reasonable.
Is it necessary?
Please clarify.
 
J

jan V

I have created a class which extends Frame and do not implement the
Serializable interface as in the declaration of class.
But still the IDE is giving the warning:
The serializable class 'AnyClass' does not declare a static final
serialVersionUID field of type long.
This is happening with most of the classes.
Using QuickFix to generate serialVersionUID for each class does not
seem to be reasonable.

You can just add a line like

// pin the serial version ID down so that we can let this class evolve a
bit without code
// blowing up with incompatible class exceptions.

static final long serialVersionUID = -1L;

... the exact value is not important. The important thing is that
(serialization) compatible classes retain the same value.
 
J

Jan Peter Stotz

Sameer said:
I am using Eclipse 3.1.
I have created a class which extends Frame and do not implement the
Serializable interface as in the declaration of class.
But still the IDE is giving the warning:
The serializable class 'AnyClass' does not declare a static final
serialVersionUID field of type long.
This is happening with most of the classes.
Using QuickFix to generate serialVersionUID for each class does not
seem to be reasonable.
Is it necessary?

Yes and No. Sun "strongly recommends" to set a static serialVersionUID:

| 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.

Taken from the API documentation of the Interface Serializable:
http://java.sun.com/j2se/1.5.0/docs/api/java/io/Serializable.html

Jan
 
R

Roland

I am using Eclipse 3.1.
I have created a class which extends Frame and do not implement the
Serializable interface as in the declaration of class.
But still the IDE is giving the warning:
The serializable class 'AnyClass' does not declare a static final
serialVersionUID field of type long.
This is happening with most of the classes.
Using QuickFix to generate serialVersionUID for each class does not
seem to be reasonable.
Is it necessary?
Please clarify.
It's not necessary as long as you aren't going to serialize your class.

You can configure Eclipse to ignore this problem. For Eclipse 3.1:
Window -> Preferences -> Java -> Compiler -> Errors/Warnings ->
Potential programming problems -> Serializable class without
serialVersionUID -> Ignore.
--
Regards,

Roland de Ruiter
` ___ ___
`/__/ w_/ /__/
/ \ /_/ / \
 
J

John C. Bollinger

Sameer said:
I am using Eclipse 3.1.
I have created a class which extends Frame and do not implement the
Serializable interface as in the declaration of class.

You do not declare Serializable, but you inherit it from Frame.
But still the IDE is giving the warning:
The serializable class 'AnyClass' does not declare a static final
serialVersionUID field of type long.
This is happening with most of the classes.
Using QuickFix to generate serialVersionUID for each class does not
seem to be reasonable.
Is it necessary?

It is a good idea, provided that you are willing to actually *use* the
mechanism by updating the ID whenever you make a change that introduces
a serialization incompatibility. You SHOULD do this, but if you choose
not to do then IMO it is better to not declare a serialVersionUID at all
than to lie about serial version compatibility.

You may also want to consider whether it is really appropriate to
subclass Frame. Unless you are writing a reusable custom GUI component,
it is far more likely that your classes USE or HAVE Frames than that
they ARE Frames. The distinction is perhaps murkier for GUI components
than for many other kinds of classes, but it is no less important. I do
little GUI programming, but in the little I do, I generally avoid
subclassing the standard components.
 
R

Roedy Green

Using QuickFix to generate serialVersionUID for each class does not
seem to be reasonable.
Is it necessary?

You want to put in an explicit serialVersionUID with specific value.
Otherwise, every time you sneeze the calculated value will change and
invalidate your serialised datafiles. Manually, you can change the
value only when the structure truly changes. On the other paw, it is
up to you to change it when the layout or names change.

see http://mindprod.com/jgloss/serialization.html
 
E

E.J. Pitt

John said:
It is a good idea, provided that you are willing to actually *use* the
mechanism by updating the ID whenever you make a change that introduces
a serialization incompatibility. You SHOULD do this, but if you choose
not to do then IMO it is better to not declare a serialVersionUID at all
than to lie about serial version compatibility.

You should *not* do this. You should leave the serialVersionUID the same
for all versions of a class and let the serialization code figure out
whether versions are serialization-compatible. If you arrive at a
version which is not, you can then provide read/writeObject methods or a
serialPersistentFields member to overcome the differences. If you just
change the serialVersionUID you have broken compatibility permanently
and one day you will rue the day ...
 
A

Andrea Desole

John said:
It is a good idea, provided that you are willing to actually *use* the
mechanism by updating the ID whenever you make a change that introduces
a serialization incompatibility. You SHOULD do this, but if you choose
not to do then IMO it is better to not declare a serialVersionUID at all
than to lie about serial version compatibility.

good point. How about people forgetting it? I am working with a client
server application. Both client and server should have the same version,
so versioning is, at least at the moment, no issue. Still, considering
that Sun strongly recommends it, I would prefer to use the
serialVersionUID, at least for the class that really are serialized
(that is, the classes that go over the network). But the main reason is
that I am also having problems when testing the client (built with
Eclipse) that connects to a server (built with Ant/javac). I always get
version mismatch. The only way I can do it is first build with Eclipse
and then with Ant, without cleaning.
Still, people are concerned about using serialVersionUID, because people
might forget to update it when necessary.
 
M

megagurka

E.J. Pitt skrev:
You should *not* do this. You should leave the serialVersionUID the same
for all versions of a class and let the serialization code figure out
whether versions are serialization-compatible. If you arrive at a
version which is not, you can then provide read/writeObject methods or a
serialPersistentFields member to overcome the differences. If you just
change the serialVersionUID you have broken compatibility permanently
and one day you will rue the day ...

Incorrect. Whenever you change a class in a way that breaks the normal
serialization mechanism, you should increase the serialVersionUID of
the class and implement readObject (no need to implement writeObject)
to be able to read objects of both class versions.

If you never change serialVersionUID it wouldn't be needed at all.

/JN
 
M

megagurka

megagurka skrev:
E.J. Pitt skrev:


Incorrect. Whenever you change a class in a way that breaks the normal
serialization mechanism, you should increase the serialVersionUID of
the class and implement readObject (no need to implement writeObject)
to be able to read objects of both class versions.

If you never change serialVersionUID it wouldn't be needed at all.

Sorry, seems I'm mistaken :-X. I did some testing and the
serialVersionUID is checked BEFORE readObject in the class is called,
making it impossible to change serialVersionUID if you want to be able
to read old versions of the class. This seems stupid to me, as being
able to read the serialVersionUID from the stream in readObject would
facilitate implementing backward compatible deserialization. Is there a
good reason why the serialVersionUID is checked before readObject is
called?

/JN
 
J

John C. Bollinger

E.J. Pitt said:
You should *not* do this. You should leave the serialVersionUID the same
for all versions of a class and let the serialization code figure out
whether versions are serialization-compatible. If you arrive at a
version which is not, you can then provide read/writeObject methods or a
serialPersistentFields member to overcome the differences. If you just
change the serialVersionUID you have broken compatibility permanently
and one day you will rue the day ...

If you are attempting to deserialize an object of an earlier class
version into an object of a later class version then it is possible, but
not certain, that you can sensibly patch up the differences with a
readObject() method. Going the other way you are out of luck,
*especially* if you need to pass the same object back to the original
sender. With this degree of uncertainty, it is safer IMO to indeed
require compatible class versions for interoperability. If you have a
requirement for indefinite interversion compatibility then a custom
persistence/exchange mechanism is warranted.
 
R

Roedy Green

Incorrect. Whenever you change a class in a way that breaks the normal
serialization mechanism, you should increase the serialVersionUID of
the class and implement readObject (no need to implement writeObject)
to be able to read objects of both class versions.

IIRC there is some ability in the standard read object methods to read
a file that is broken. It fishes out the fields it can and zeros
others. I have never used this, but it might be worth looking into a
as way of dealing with changed files layouts.
 
E

E.J. Pitt

megagurka said:
Sorry, seems I'm mistaken :-X.

Thank you. Having the same value for serialVersionUID tells
Serialization either that its own versioning mechanisms are sufficient
or that you have compensated by providing some selection or combination
of readObject(), writeObject(), writeReplace(), readResolve(), or
obhectStreamFields[] so that it will be sufficient.

As John Bollinger says, if you have broken compatibility so badly that
none of this can work you might well want to change the
serialVersionUID, although what I would be doing in this case is
probably to increment the class-name.
 
S

Sameer

Let me add that the AppPerfect code analyser for Eclipse shows that not
having serialVersionUID for a class is a HIGHLY SEVERE code convention
breaking fact.
Thanks all of you for discussion about this post.
 
D

Dale King

Roland said:
It's not necessary as long as you aren't going to serialize your class.

You can configure Eclipse to ignore this problem. For Eclipse 3.1:
Window -> Preferences -> Java -> Compiler -> Errors/Warnings ->
Potential programming problems -> Serializable class without
serialVersionUID -> Ignore.

While you can configure the compiler to ingore it, I for one think this
is a problem with Java. The problem is that if a class is serializable
then all subclasses are also considered serializable. There is no way to
override that and say that a class is not serializable if a superclass
is serializable. It doesn'e alway make sense for a class to be
serializable just because it extends a class that is.

The real solution is that Java needs to support a Serializable
annotation that has precedence over the Serializable marker interface.
This annotation would have a boolean value that by default is true, but
can be specified as false to handle cases where you don't need
serialization.
 
O

Oliver Wong

Dale King said:
While you can configure the compiler to ingore it, I for one think this is
a problem with Java. The problem is that if a class is serializable then
all subclasses are also considered serializable. There is no way to
override that and say that a class is not serializable if a superclass is
serializable. It doesn'e alway make sense for a class to be serializable
just because it extends a class that is.

The real solution is that Java needs to support a Serializable annotation
that has precedence over the Serializable marker interface. This
annotation would have a boolean value that by default is true, but can be
specified as false to handle cases where you don't need serialization.

What about the concept that you can use a subclass anywhere you could
have used its ancestor class? This implies that if you subclass a
serializable class, your subclass must also be serializable.

- Oliver
 
R

Roedy Green

What about the concept that you can use a subclass anywhere you could
have used its ancestor class? This implies that if you subclass a
serializable class, your subclass must also be serializable.
Just to clarify. All interfaces implemented are inherited by all
subclasses, so you can't write a subclass of a Serializable class that
is not marked serializable. Whether it WORKS or not is another matter.
 
D

Dale King

Oliver said:
What about the concept that you can use a subclass anywhere you could
have used its ancestor class? This implies that if you subclass a
serializable class, your subclass must also be serializable.

But that doesn't really apply in this case. We are not talking about
changing the API in a subclass violating the Liskov substitution
principle. Serialization is really a property of the exact instance.

Consider a GUI component that shows the output of a connection to some
other piece of hardware. The GUI component that it extends is
serializable, but it doesn't make sense to serialize this subclass
because you really can't serialize the connection itself. You can't
really deserialize it and restore the connection.

This example is somewhat bad because it is one where perhaps composition
should have been used instead of inheritance. But the principle is
valid. You can subclass an object that is serializable adding data that
is not serializable such that it makes no sense to serialize the subclass.
 
C

Chris Uppal

Dale said:
This example is somewhat bad because it is one where perhaps composition
should have been used instead of inheritance. But the principle is
valid. You can subclass an object that is serializable adding data that
is not serializable such that it makes no sense to serialize the subclass.

But if you do that then substitutability breaks -- specifically the ability to
use the non-serialisable object as a component within a larger object. Since
you mention composition, it seems worthwhile to emphasise that.

-- chris
 
O

Oliver Wong

Dale King said:
But that doesn't really apply in this case. We are not talking about
changing the API in a subclass violating the Liskov substitution
principle. Serialization is really a property of the exact instance.

Consider a GUI component that shows the output of a connection to some
other piece of hardware. The GUI component that it extends is
serializable, but it doesn't make sense to serialize this subclass because
you really can't serialize the connection itself. You can't really
deserialize it and restore the connection.

This example is somewhat bad because it is one where perhaps composition
should have been used instead of inheritance. But the principle is valid.
You can subclass an object that is serializable adding data that is not
serializable such that it makes no sense to serialize the subclass.

I realize now that we are actually in agreement, but that I had misread
your original post. I seemed to have focused on "It doesn't alway make sense
for a class to be serializable just because it extends a class that is." and
rather than interpreting that at a high OO level, I was thinking in terms of
Java semantics, where it DOES make sense because Serializable is an
interface, and so all the subclasses must be serializable if they extend a
parent which is serializable (due to the semantics of interface and
inheritance in Java).

Basically, I think we are in agreement that "making Serializable an
interface" was the wrong approach.

- Oliver
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,733
Messages
2,569,439
Members
44,829
Latest member
PIXThurman

Latest Threads

Top