What happens if i'll try to serialize an attribute which is static?
thanks
From this article:
Tip 1: Handling Static Variables
Java classes often hold some
globally relevant value in a static
class variable. We won't enter into
the long history of the debate over
the propriety of global variables -
let's just say that programmers
continue to find them useful and the
alternatives suggested by purists
aren't always practical.
For static variables that are
initialized when declared,
serialization doesn't present any
special problems. The first time the
class is used, the variable in
question will be set to the correct
value.
Some statics can't be initialized this
way. They may, for instance, be set by
a human during the running time of the
program. Let's say we have a static
variable that turns on debugging
output in a class. This variable can
be set on a server by sending it some
message, perhaps from a monitor
program. We'll also imagine that when
the server gets this message, the
operator wants debugging turned on in
all subsequent uses of the class in
the clients that are connected to that
server.
The programmer is now faced with a
difficulty. When the class in question
arrives at the client, the static
variable's value doesn't come with it.
However, it contains the default
static state that's set when the
class's no-argument constructor is
called by writeObject(). How can the
client programs receive the new
correct value?
The programmer could create another
message type and transmit that to the
client; however, this requires a
proliferation of message types,
marring the simplicity that the use of
serialization can achieve in
messaging. The solution we've come up
with is for the class that needs the
static transmitted to include a
"static transporter" inner class. This
class knows about all the static
variables in its outer class that must
be set. It contains a member variable
for each static variable that must be
serialized. StaticTransporter copies
the statics into its member variables
in the writeObject() method of the
class. The readObject() method
"unwraps" this bundle and transmits
the server's settings for the static
variables to the client. Since it's an
inner class, it'll be able to write to
the outer class's static variables,
regardless of the level of privacy
with which they were declared.
And from another article:
Static or transient data
However, this "ease" is not true in
all cases. As we shall see,
serialization is not so easily applied
to classes with static or transient
data members. Only data associated
with a specific instance of a class is
serialized, therefore static data,
that is, data associated with a class
as opposed to an instance, is not
serialized automatically. To serialize
data stored in a static variable one
must provide class-specific
serialization.
Similarly, some classes may define
data members to use as scratch
variables. Serializing these data
members may be unnecessary. Some
examples of transient data include
runtime statistics or hash table
mapping references. These data should
be marked with the transient modifier
to avoid serialization. Transient, by
definition, is used to designate data
members that the programmer does not
want or need to be serialized. See
Java in a Nutshell, page 174: mouse
position, preferred size, file handles
(machine specific (native code)).
When writing code if something is
declared transient, then this triggers
(to programmer) necessity of the
posibility of special code for
serialization later.
To serialize an object, you create
some sort of OutputStream object and
then wrap it inside an
ObjectOutputStream object. At this
point you only need to call
writeObject() and your object is
magically serialized and sent to the
OutputStream. To reverse the process,
you wrap an InputStream inside an
ObjectInputStream and call
readObject(). What comes back is, as
usual, a handle to an upcast Object,
so you must downcast to set things
straight. If you need to dynamically
query the type of the object, you can
use the getClass method. Specifically
dk.getClass.getName() returns the name
of the class that dk is an instance
of. I.e., this asks the object for the
name of its corresponding class
object. (Hmmm, True, but what about
syntax? I still need to know what it
is to declare it...too bad) (C++ can
do this in one operation (dynamic_cast
(gives null if wrong type)), java can
use instanceof operator to check if it
is what I think (see Core Java, Ch5
Inheritence, Casting section)
Yes, we can defnitely serialise the static variable, but we wont be able to get any purpose of serialisation on the static variables.
Why because the Static variables are not bounded to any objects in scope.
We serialize objects to store them so they can retrieved later for any use.
Only the Transient varibles you cant make them to get serialised.
You can serialize the value of a static variable / attribute. But strictly speaking, you don't serialize a variable or attribute in its own right, whether it is class level, instance level, or local to a method.
Normally the instance level attributes of an object are serialized as part of the parent object; i.e. the object that they are attributes of. If you translate that to class level attributes, then the notional parent is the class. While there is a runtime object that denotes this class (i.e. the java.lang.Class returned by this.getClass()), this object is not serializable. So from that perspective, a class level (static) attribute is not serializable.
Related
According to Java Concurrency in Practice book:
Informally, an object's state is its data, stored in state variables such as instance or static fields.
As far as I understand from Java concepts or in general, state / instance variables define the object state. As far as I know, the static fields belong to class variables. In what case does static fields define object's state?
It sounds a bit ambiguous to me - one could probably argue that static variables are inherently object state that is the same for all objects of a given type.
Personally, however I don't think that static variables constitute object state. This quote from the Oracle Java tutorial seems to support my understanding.
Sometimes, you want to have variables that are common to all objects.
This is accomplished with the static modifier. Fields that have the
static modifier in their declaration are called static fields or class
variables. They are associated with the class, rather than with any
object. Every instance of the class shares a class variable, which is
in one fixed location in memory. Any object can change the value of a
class variable, but class variables can also be manipulated without
creating an instance of the class.
For example, suppose you want to create a number of Bicycle objects
and assign each a serial number, beginning with 1 for the first
object. This ID number is unique to each object and is therefore an
instance variable. At the same time, you need a field to keep track of
how many Bicycle objects have been created so that you know what ID to
assign to the next one. Such a field is not related to any individual
object, but to the class as a whole.
With that said, static variables can keep track of the status of the overall application state, which is what another question based on the same books speaks to: Object's state in public static fields
From Wiki
In object-oriented programming, there is also the concept of a static
member variable, which is a "class variable" of a statically defined
class, i.e., a member variable of a given class which is shared across
all instances (objects), and is accessible as a member variable of
these objects
Since static variable in class is shared across all the instances (objects) of class, it plays a role directly or indirectly in state of that object.
Being a newbie, I'm trying to understand serialization and I don't get why one would need to reassign static fields after deserialization (as some suggest in order to keep original values) if by definition all objects of the same class have the same values of static parameters. Isn't it true that a new object automatically receives all static parameters of its class? I mean if deserialization nullifies object's static members and we keep the original object wouldn't that mean that there will be two objects of the same class with different values of static parameters? How's that possible or how am I wrong?
EDIT:
It seems that I wasn't clear enough and I'm sorry about that.
When writing my first sentence I was keeping in mind Bruce Eckel's "Thinking in Java" (4th Ed.). I'm not sure if I can attach a few scans of his book without violating copyright but I actually stumbled upon the last example in "Object serialization" chapter (pp.715-718). By means of his io/StoreCADState.java and io/RecoverCADState.java Eckel gets objects of the same class with different static values. He doesn't go deep enough for me into explanation and I feel totally confused.
I know that static members belong to a class not an object. Although I'm not sure now what it means precisely. I used to believe it implied that whenever an object is created a set of static parameters is 'taken' from the class description and 'added' to an object. If this is correct then why they are not 'added' to an object after deserialization when Object instance being cast to a specific class?
Have a look at the Javadoc for static members here. This is what it says:
They are associated with the class, rather than with any object.
As static members are never associated with any object, they are never stored while serializing the object. Also, new object won't automatically receive all static parameters as they have nothing to do with serialization-deserialization of the objects. If you are trying to store static variables with objects then I'd say it's a design flaw. We should rather declare them as non static if we want to persist their values with objects.
Update:
If you want to store non serializable fields with object then you can do so by writing your implementation of readObject() and writeObject() methods. Have a look at the answer of this SO question for example.
How does serialization reconcile static members?
It doesn't.
I don't get why one would need to reassign static fields after deserialization
You don't.
(as some suggest in order to keep original values)
They're wrong.
if by definition all objects of the same class have the same values of static parameters.
Objects don't have values of static parameters at all. The static members are in the class, not in the object.
Isn't it true that a new object automatically receives all static parameters of its class?
No.
I mean if deserialization nullifies object's static members
It doesn't.
and we keep the original object wouldn't that mean that there will be two objects of the same class with different values of static parameters?
No, because it doesn't happen.
How's that possible
It isn't.
or how am I wrong?
Several ways. Serialization does precisely nothing with static members.
EDIT
It seems that I wasn't clear enough and I'm sorry about that.
You were clear enough. You're just fundamentally mistaken about several things.
When writing my first sentence I was keeping in mind Bruce Eckel's "Thinking in Java" (4th Ed.). I'm not sure if I can attach a few scans of his book without violating copyright
You can't (shouldn't) post images of text here, but you can quote a bit of the book under 'fair use' provisions.
but I actually stumbled upon the last example in "Object serialization" chapter (pp.715-718). By means of his io/StoreCADState.java and io/RecoverCADState.java Eckel gets objects of the same class with different static values.
Impossible. You must have misunderstood. Or else he is using different class loaders, which is a complication not mentioned in your question.
He doesn't go deep enough for me into explanation and I feel totally confused. I know that static members belong to a class not an object. Although I'm not sure now what it means precisely. I used to believe it implied that whenever an object is created a set of static parameters is 'taken' from the class description and 'added' to an object.
No. The static data stays where it is, in the class. If there were multiple copies of it, it couldn't possibly work, or be describable as 'static'.
If this is correct
It isn't.
then why they are not 'added' to an object after deserialization
Because Serialization doesn't deal with static objects in any way.
when Object instance being cast to a specific class?
And that process takes place after Serialization, not during it, and doesn't have anything to do with static data either.
Because static members belong to the class, not to the object, they're not serialized or deserialized by default.
A Class with the same name and different values in static members can be only in another namespace (loaded by another ClassLoader).
Read this to understand: How to serialize static data members of a Java class?
In a process of leaning java serialization concept, i was puzzled at one point. In java serialization process, we use 2 keywords to prevent serialization, i.e.., transient and static. If i don't want to save an instance variable, which keyword should i use, both does exactly the same.
Class A implements Serializable{
private static int x;
private transient int y;
private transient static int x;
}
In the above code all the three instance variables are not saved in a process of serialization. Which keyword is apt and recommended to prevent serialization. Why does two keywords have almost the same functionality. What is the recommended way of declaration to prevent serialization. Correct me if I'm wrong, I'm still learning.
The static keyword transforms an instance variable into a static variable. A side-effect is that the field is not serialized anymore... because it's not a field anymore.
A static variable is a variable of the class. An instance variable is a variable of the object, or instance of the class. You can't blindly go from one to the other.
Read the tutorial page about instance and static variables.
The transient keyword is the right keyword to use, of course.
You are confused: static fields are not instance variables, they are class-wide variables. By declaring a field static, the same field is shared among all instances of this class - it is not part of any specific object anymore, which leads to it not being serialized.
To specifically prevent serialization only transient is applicable...
Transient (and in JAXB XmlTransient) signify that the data is ephemeral and not of permanent importance and thus should just be ignored when it comes to matters of persistence.
Static means the value applies that the class level and thus serializing/deserializing it for multiple instances would be unsafe as values would collide.
Well, Let me define serialization once more.
A serialization is a process in which we persist state of an object.
So, is any static variable is part of an object's state ?..No absolutely not. It is the data which is shared among all objects of a class. So obviously, any static variable is not supposed to be serialized with object's state.
let's assume, we are allowed to persist an object's state. later on, if this variable is changed by some other object/class itself, and if we try to de-serialize the object then what value this static variable will hold. There will be a clash.
So if you want to prevent any instance variable from being serialized , do use transient.
when you will de-serialize the object it will be initialized with a default value.
I need to persist several classes with A LOT of static fields (which are arrays filled & modified during the runtime). It would take a lot of effort to convert from static fields to instance vars, so I'd rather go for a quick solution, if any.
So far the path of least resistance is to cook my own writeObject() for each class.
Alternatively, i dont need Serialization as such - any mechanism to store/load an object from persistent storage will do. E.g. XMLDecoder to decompose the bean objects, etc.
You could write a method to use reflection to serialize all static methods. A static method can be marked transient which would normally be redundant, but you could use this to highlight static fields you don't want to serialize. You can call this method from your writeObject() to save you having to do this for every field.
I'd create a new class that gathers all those static fields, lets call it StaticInfoClass. In StaticInfoClass create all the fields non-static. Create a property in the old class that is type of StaticInfoClass. All instances of the your original class will hold a reference to a unique instance of StaticInfoClass, that will contain all the arrays filled and modified during the runtime. If you have threads make sure you make it a bean with synchronized methods to avoid race conditions.
With this approach, in essence, you are implementing static fields without actually using the static modifier. This simple approach should easy a lot your serialization and deserialization problems and most frameworks will handle it very easily.
Also remember that static fields and global state in programs are normally a bad practice, it should be avoided. I tend to not use static if it is not to declare constants or other trivial data structures that definitely do not changed in runtime.
Have not tried this but might work. if your class defines an array of ObjectStreamField objects named serialPersistentFields , then you can explicitly declare the specific fields saved. You can shove any value into it, even the static fields.
private static String lastUser;
private static int maxAge;
private final static ObjectStreamField[]
serialPersistentFields = {
new ObjectStreamField(
"lastUser", String.class),
new ObjectStreamField("maxAge", int.class)
};
Then you will have to implement readObject, to fetch these values and set it for your static variables. So basically this mechanism allows you to marshall/unmarshall fields from anywhere via serialization. You just need to know what to do with them once you read them back. I would still recommend paying the price for moving your statics to member variables.
details : http://java.sun.com/developer/technicalArticles/ALT/serialization/
I have a class that is serialised. Now I need to add a new variable into the class, with setter and getter methods. This class is sent over wire in RMI.
Without changing the UID, can I add new parameters and getter and setter methods for it? I tried to write an example class that is sent over wire, and did not change the UID, and added new parameters and getter and setter methods for it. On the other end, I tested it and I still got the values properly. I had assumed, if I add new parameters, getter and setter methods, I need to change the UID. Am I wrong?
If you hard-code the SerialVersionUID of a class, (to 1L, usually), store some instances, and then re-define the class, you basically get this behavior (which is more or less common sense):
New fields (present in class definition, not present in the serialized instance) are assigned a default value, which is null for objects, or the same value as an uninitialized field for primitives.
Removed fields (not present in class definition but present in the serialized instance) are simply ignored.
So the general rule of thumb is, if you simply add fields and methods, and don't change any of the existing stuff, AND if you're OK with default values for these new fields, you're generally OK.
Wow, a lot of bad information.
Java serialization is +very+ robust. There are a very well defined set of rules governing backwards compatibility of objects with the same uid and different data. the basic idea is that as long as you don't change the the type of an existing member, you can maintain the same uid without data issues.
that said, your code still needs to be smart about handling classes with potentially missing data. the object may deserialize correctly, but there may not be data in certain fields (e.g. if you added a field to the class and are deserializing an old version of the class). if your code can handle this, than you can probably keep the current uid. if not, then you should probably change it.
in addition to the pre-defined rules, there are advanced usage scenarios where you could even change the type of existing fields and still manage to deserialize the data, but that generally only necessary in extreme situations.
java serialization is very well documented online, you should be able to find all this information in the relevant sun/oracle tutorials/docs.
This only matters if you let Java generate a default UID for your class. It uses the actual members and methods of the class to generate it, thus making it invalid once you change the class structure. If you provide an UID for your class then this only matters if you need to deserialize older versions of your class from a file and such.
Want to define few point to highlight the changes which impacts serialization.
Below you will find the link to Oracle Java Docs for more details.
Incompatible Changes
Incompatible changes to classes are those changes for which the guarantee of interoperability cannot be maintained. The incompatible changes that may occur while evolving a class are:
Deleting fields
Moving classes up or down the hierarchy
Changing a nonstatic field to static or a nontransient field to transient
Changing the declared type of a primitive field
Changing the writeObject or readObject method so that it no longer writes or reads the default field data or changing it so that it attempts to write it or read it when the previous version did not.
Changing a class from Serializable to Externalizable or vice versa.
Changing a class from a non-enum type to an enum type or vice versa.
Removing either Serializable or Externalizable.
Adding the writeReplace or readResolve method to a class, if the behavior would produce an object that is incompatible with any older version of the class.
Link from where the above information is taken
http://docs.oracle.com/javase/7/docs/platform/serialization/spec/version.html#6678