问题
When class implements Serializable in Eclipse, I have two options: add default serialVersionUID(1L)
or generated serialVersionUID(3567653491060394677L)
. I think that first one is cooler, but many times I saw people using the second option. Is there any reason to generate long serialVersionUID
?
回答1:
As far as I can tell, that would be only for compatibility with previous releases. This would only be useful if you neglected to use a serialVersionUID before, and then made a change that you know should be compatible but which causes serialization to break.
See the Java Serialization Spec for more details.
回答2:
The purpose of the serialization version UID is to keep track of different versions of a class in order to perform valid serialization of objects.
The idea is to generate an ID that is unique to a certain version of an class, which is then changed when there are new details added to the class, such as a new field, which would affect the structure of the serialized object.
Always using the same ID, such as 1L
means that in the future, if the class definition is changed which causes changes to the structure of the serialized object, there will be a good chance that problems when trying to deserialize an object.
If the ID is omitted, Java will actually calculate the ID for you based on fields of the object, but I believe it is an expensive process, so providing one manually will improve performance.
Here's are a couple of links to articles which discuss serialization and versioning of classes:
- JDC Tech Tips: February 29, 2000 (link broken as of February 2013)
- Discover the secrets of the Java Serialization API
回答3:
The main reason for the generated one would be to make it compatible with an existing version of the class that already has persisted copies.
回答4:
The "long" default of the serialVersionUID
is the default value as defined by the Java Serialization Specification, calculated from the default serialization behaviour.
So if you add the default version number, your class will (de-)serialize faster as long as nothing has structurally changed, but you'll have to take care that if you change the class (add/remove fields) you also update the serial number.
If you do not have to be compatible to existing bit streams, you can just put 1L
there and increment the version as needed when something changes. That is, when the default serialisation version of the changed class would be different from the default version of the old class.
回答5:
You absolutely should create a serialVersionUID every time you define
a class that implements java.io.Serializable
. If you don't, one will
be created for you automatically, but this is bad. The auto-generated
serialVersionUID is based on the method signatures of your class, so
if you change your class in the future to add a method (for example),
deserializing the "old" versions of the class will fail. Here's what
can happen:
- Create the first version of your class, without defining the serialVersionUID.
- Serialize an instance of your class to a persistent store; a serialVersionUID is automatically generated for you.
- Modify your class to add a new method, and redeploy your application.
- Attempt to deserialize the instance that was serialized in step 2, but now it fails (when it should succeed), because it has a different auto-generated serialVersionUID.
回答6:
If you don't specify a serialVersionUID then Java makes one on the fly. The generated serialVersionUID is that number. If you change something in your class that doesn't really make your class incompatible with previous serialized verisons but changes the hash, then you need to use the generated very-large-number serialVersionUID (or the "expected" number from the error message). Otherwise, if you are keeping track of everything yourself, 0, 1, 2... is better.
回答7:
When you use serialVersionUID(1L) rather than generating serialVersionUID(3567653491060394677L) you are saying something.
You are saying that you are 100% confident that no system that will ever touch this class that has an incompatible serialized version of this class with a version number of 1.
If you can think of any excuse for it's serialized version history to be unknown, that might be hard to say with confidence. In it's lifetime, a successful class will be maintained by many people, live in many projects, and reside in many systems.
You can agonize over that. Or you can play the lottery hoping to lose. If you generate the version you have a tiny chance of things going wrong. If you assume "Hey I bet no one used 1 yet" your odds are larger than tiny. It's precisely because we all think 0 and 1 are cool that you have higher odds of hitting them.
-
When you generate serialVersionUID(3567653491060394677L) rather than use serialVersionUID(1L) you are saying something.
You are saying people may have either manually created or generated other version numbers over the history of this class and you don't care because Longs are freaking big numbers.
Either way unless you perfectly know the history of version numbers used when serializing the class in the entire universe of where it has or will ever exist, you're taking a chance. If you have the time to make 100% sure 1 is AOK, go for it. If that's to much work, go ahead and blindly generate the number. You're more likely to win the lottery than to have that go wrong. If it does, let me know and I'll buy you a beer.
With all this talk of playing the lottery I may have given you the impression that serialVersionUID is generated randomly. In fact as long as the range of numbers is evenly distributed over every possible value of a Long that would be fine. However, it's actually done this way:
http://docs.oracle.com/javase/6/docs/platform/serialization/spec/class.html#4100
The only difference you get with that is you don't need a source of random. You're using the changes in class itself to change the result. But according to the pigeonhole principle there is still a chance it could go wrong and have a collision. It's just incredibly unlikely. So good luck getting a beer out of me.
However, even if the class will only ever live in one system and one code base, thinking that incrementing the number by hand gives you zero chance of collisions just means you don't understand humans. :)
回答8:
Well, serialVersionUID is an exception to the rule that “static fields don’t get serialized”. ObjectOutputStream writes every time the value of serialVersionUID to the output stream. ObjectInputStream reads it back and if the value read from the stream does not agree with the serialVersionUID value in the current version of the class, then it throws the InvalidClassException. Moreover, if there is no serialVersionUID officially declared in the class to be serialized, compiler automatically adds it with a value generated based on the fields declared in the class.
回答9:
Because in many cases default id is not unique. so we create id for making unique concept.
回答10:
To add to @David Schmitts answer, as a rule of thumb I would always use the default 1L out of convention. I've only had to go back and change some of them a few times, but I knew that when I made the change and updated the default number by one each time.
At my current company they require the auto-generated number so I use that for convention, but I prefer the default. My take is, if it's not a convention where you work, use the default, unless you think you will be constantly changing the structure of you serialized classes for some reason.
来源:https://stackoverflow.com/questions/888335/why-generate-long-serialversionuid-instead-of-a-simple-1l