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.
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.
Transient and static variable can not Serialize
According to Joshua Bloch’s excellent book “Effective Java Programming Language Guide”, “ the volatile modifier guarantees that any thread that reads a field will see the most recently written value "
but what about volatile be serialized or not.
A volatile is typically serialized by Java Object Serialization. The threading / JMM properties of volatile are orthogonal to serialization.
Incidentally, it is possible to serialize a transient or static variable, if you code custom writeObject / readObject methods to do this. But, this isn't done by the default serializer.
You wouldn't expect a transient variable to be serialized. After all transient is essentially a hint to not include the field in a serialization.
The reason that static variables are not included in an object serializations (by default) is that statics don't "belong" to a specific object.
Yes, it can be serialized. The field modifier volatile is used for the Java Memory Model to ensure that all Threads see a consistent value. It does not restrict its persistence.
I do not understand that why we need transient keyword to prevent serialization of a particular data member. We can also make it static because static data member can not be serialized. Please guide me if I am wrong!
static does not just make a member not serialized; it also means that there is only one copy of that field for the entire class. If you want there to be a copy of that field for each object, but do not want that object to be serialized, you need transient; static will do something completely different.
Making variables static without fully understanding this is a massively common source of bugs for new Java developers.
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/
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.