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/
Related
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?
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 know what static is, but just not sure when to use it.
static variable:
I only used it for constant fields. Sometimes there are tens of constants in a class, so using static constants can save lots of memory. Is there any other typical use cases?
static method:
I use it when I make a class about algorithms. For example, a class which provides different sorting algorithms. Is it against OOP design? I think it is better to maintain this way rather than implementing sorting algorithms inside each class that needs to use them. Am I wrong? What are some good use cases?
Also, are there any performance difference between using static and non-static fields/methods?
You are describing cases where you've used static, but this doesn't quite explain fundamentally why you would use static vs non-static - they are more than just keywords for constants and utility methods.
When something is not static (instance), it means that there is an instance of it for each instance of the class. Each one can change independently.
When something is static, it means there is only one copy of it for all instances of the class, so changing it from any location affects all others.
Static variables/methods typically use less memory because there is only one copy of them, regardless of how many instances of the class you have. Statics, when used appropriately, are perfectly fine in object oriented design.
If you have a method/variable that you only need one instance of (e.g. a constant or a utility method), then just make it static. Understand though that making a method static means it cannot be overridden. So if you have a method you want to override in a subclass, then don't make it static.
The general rule of thumb is - if you need only one copy of it, make it static. If you need a copy per instance, then make it non static.
Is there any other typical use cases?
Global Variables
Is it against OOP design?
Not exaclty, the point is that static methods are stateless since you don't need a particular instance of a class. My favorite approach is for utility methods (like Apache Commons). But you may be aware that some methods may be better placed as class members instead of static.
Also static methods can make class testability harder once you can't override these methods or replace by mock implementation.
Performance difference ?
There's a performance Android recommendation from Google that says "prefer static over virtual":
http://developer.android.com/training/articles/perf-tips.html#PreferStatic
I'm not sure it's true for JVM since Android uses a different VM, but it makes sense given the reasons the link points out:
If you don't need to access an object's fields, make your method static. Invocations will be about 15%-20% faster. It's also good practice, because you can tell from the method signature that calling the method can't alter the object's state."
My personal rule of thumb is that static things are "just hanging out there". They are things that (disclaimer, not entirely true) are global, but make sense to include with this one particular class.
Static fields are good if you find yourself loading some heavyweight objects repeatedly. For instance, the project I'm working on now has a toggle between two images. These are static fields that are loaded with the application and kept in memory, rather than reloading them every time and letting GC take care of the mess.
Apart from very specific situations, I use static (and final) variables for constants only. It's a totally valid to use them, of course.
I tend to avoid static utility methods, because they make it harder to write unit tests for the code (mocking the results of the method invocation). When you start developing Test Driven way, this issue becomes quite apparent. I prefer using dependency injection and singleton beans (though it depends on your needs and situation).
Static variables belong to a class, hence shared by all the objects, so memory usage is less if you really want the varible to be shared. If you declare the variable as public and static, then it is globally available for everyone.
Static methods are generally the utility methods, depending on the access modifier, those can be used within a class or across the classes. Static utility class will help to reduce the memory usage again because you need not to create the object to call those methods.
The static field has one value among all objects and they call it Class member also because it's related to the class.
You can use static filed as a utility.
an example just Assume we need to know how many instances we have :
class Counter
public class Counter {
public static int instanceCount ;
public Counter()
{
instanceCount++;
}
public int getInstanceCount()
{
return instanceCount;
}
}
After creating two instances of Counter Class. But they share the same instanceCount field because it's a static field so the value of instanceCount will become the same in firstCounter and secondCounter .
Class main
Counter firstCounter = new Counter();
// will print 1
System.out.println(co.getInstanceCount());
// will print 2
Counter secondCounter = new Counter();
System.out.println(co1.getInstanceCount());
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.
I am looking for some efficient way for building a immutable class, just like Java's String class.
All the fields must be
private and preferably final
Ensure the class cannot be
overridden - make the class final,
or use static factories and keep
constructors private
Fields must be populated from the
Constructor/Factory
Don't provide any setters for the
fields
Watch out for collections. Use
Collections.unmodifiable*. Also, collections should contain only immutable Objects
All the getters must provide
immutable objects or use defensive copying
Don't provide any methods that
change the internal state of the
Object.
Tom Hawtin pointed out that final can be optional. String class has a cache hash var that is only assigned when the hash function is called.
If you populate all fields using the constructor and make the fields final - you are partway there.
If the fields use custom types - you may need to make them immutable as well.
Any fields that are collections should use the unmodifiable collections - to be on the safe side.
You need to worry about the object graph!
Any methods on the object need to take care with non-final fields. E.g. String.add creates a new String. If you need to mutate one field - do so via a copy constructor.
Finally make the object final.
An object is immutable if none of its fields can be modified, so those fields must be final. If you don't want your object to be subclassed, you can make the class itself final as well, just like String is.
To easily construct an immutable object with a lot of information, you should look at the Factory Pattern
For more information, see Wikipedia