At work recently I’ve been doing an informal review of our code base, in an attempt to get together a potential code refactoring work package. I say informal because I haven’t got any official time allocated to it – currently its taking place in lunchtimes and during slack that I haven’t told management about. Along with tools like “checkstyle”:http://checkstyle.sourceforge.net/ and “QStudio pro”:http://www.qa-systems.com/products/qstudioforjava/ I’ve been able to pick up some issues which will exist in any organisation which, like ours has had no real coding standards or review process. In addition I’ve been carrying out a more general design review, and one issue that cropped up was that of singleton classes and static classes.
Those of you familiar with Java would probably of seen implementations of the singleton pattern such as this:
public class Singleton {
private static Singleton me;
private Object singletonData;
private Singleton() {
}
public static synchronized Singleton instance() {
if (me == null) {
me = new Singleton();
}
return me;
}
public void doSingletonMethod() {
//Do something with singleton data
}
}
The Singleton
has a private
constructor – the only way an instance of the class can be created is by using the static instance()
method – this method enforces that within a single JVM, only a single instance of this class may be created. Lets look at a static class with one simple method:
public class StaticClass {
private Object staticData;
public static void doStaticMethod() {
//do something with static data
}
}
So whats the difference? Well firstly to use the doSingletonMethod
on the SingletonClass
, you have to instantiate an instance of the class using the instance
method. To call doStaticMethod
we simply invoke it via the class: SingletonClass.doStaticMethod()
. So, which one should you use? A clear example of a static class would be a set of utility functions, whose only real commonality would be the fact they are all utility functions – no data is associated with the methods beyond the parameters passed in, the results of the methods, or perhaps some constant static data. A clear example of a Singleton class would be a manager class, who stores other objects and manipulates their state. Why the difference? Well, the Singleton class “feels” like its an actual thing, whereas a static class is really just a convenient collection of related functions. Anyway, these thoughts lead me to add two guidelines to my own unwritten style guide:
- If the only data it uses that isn’t passed in is all constant (read: final) data, its a static class
- If it has NO internal data at all, its a static class
- If it has non-constant data and it only makes sense to have one of them, then its a Singleton
- If it doesn’t match any of the above, its a normal class
Now to apply these rules at work….
_updated 05/09/2003_: Many thanks to R.J. and Payton for picking up some problems with my example code – thats what you get for hand coding example code rather than simply pasting in a real life example 🙂
20 Responses to “Of Singletons and Static classes”
Another thing to keep in mind is that a “static class” cannot implement an interface, since interface methods can’t be static.
This especially comes into play when you have a singleton whose implementation varies (e.g., according to platform-dependent factors).
But your staticData object can be an interface, so it gives you the flexibility you need when implementing instance()
btw, the lazy loading of a static is unnecessary, the VM will only construct a static member when it is first accessed anyway.
That, and the singleton shown here isn’t thread safe.
Related to the interface implementation by Adam, if you give the Singleton class a default or protected constructor, it can be sub-classed, allowing you to override methods in the future and the client only would need to change their Singleton.instance() method to SuperSingleton.instance().
I prefer deciding whether a static class or Singleton class as follows: “If the class maintains no state, and you cannot conceive of it maintaining state in the future, it’s static. Otherwise it’s a Singleton”.
BTW, you forgot the “return me;” at the end of instance(), and you better change the method signature to “synchronized”, or you have a race condition if the code is run in a multi-threaded environment.
Aha! Thanks for the catch Payton – that’s what I get for hand coding the code example rather than pasting actual code 🙂 Also your summation of what should or shouldn’t be a singleton class is MUCH more elegant than mine – my list amounts to pretty much the same thing, but yours is a lot neater and much easier to understand.
As for the lazy loading of the static field, are you sure on this Jed? Its seems like one of those things that could vary between JVM implementations.
Now I’m actually going to fix my singleton example to stop me looking like such an idiot 🙂
The lazy load may or may not be necessary, depending on the situation. You could have the following:
private static Singleton me = new Singleton();
In which case the race condition is completely avoided and the singleton is created when the class is loaded. However, if you do any processing in the constructor that you may want delayed until later, you’ll want the lazy instantiation.
As far as synchronization goes, check this article to see why you shouldn’t use double-checked locking on the instantiation: http://www.javaworld.com/javaworld/jw-02-2001/jw-0209-double.html
Another benefit of a singleton is the ability to use it in JSP tags. Tag support for static methods is pretty slim, so it’s often easier to pass the singleton into whatever tag you’re using.
Plus, it’s always fun when a rather clueless coworker comes up to you and asks how you can have a private constructor.
I have to admit, this has been one of the best threads I’ve seen about this topic. Time to print out Payton’s line and hang it in my cubicle.
I have to agree Jay – this thread has been informative enough that I’ve realised it really deserves a more detailed discussion. Expect a more detailed piece from me in the next few days.
I prefer to use an Object any day of the week for my singletons(http://www.sharemation.com/dhunter/public/oop/oop.html#S)
1)Objects can scale better.
2)Objects are more useful/dynamic/polymorphic.
1)I somtimes use birth control as an Anology.
Would prefer a vasectomy or castration?
Objects can reproduce like rabits if you decide need more -reverse the operation. A createRabit() factory method can always be added later.
*Question: How do Classes reproduce?
2)Dynamic proxies / mock objects / remote Stubs
can be used with objects.Objects are also easier to Unit Test
public class Singleton implements Remote… {
*Answer:They do not (Unless you are cutting & pasting – very slow & error prone)
Would it be possible to make instance field start with a “m_” before each instance field variable.
This makes it easier to identify which are local variables and which are local variables.
Do you have any commit about this?
Or could you present this as a standard in your coding.
Thank you and GOD bless you!
Instance variables starting with “m_”… That brings me back to my Visual C++ days.
In my code i tend to use an underscore prefix for all instance variables – I have seen some people using understores as a suffix. Using an m_varname as opposed to an _varname is a lot more ugly in my opinion, but as always beauty is in the eye of the beholder!
Guess what is printed by Main:
// Main.java
class A {
// A is a singleton. The getInstance() method is even synchronized.
private static A instance;
public synchronized static A getInstance() {
return (instance == null) ? (instance = new A()) : instance;
}
// A uses B
private B b;
private A() {
b = new B();
}
}
class B {
// B caches the only instance of A
public static A a = A.getInstance();
}
class Main {
public static void main(String[] args) {
System.out.println(A.getInstance() == B.a);
}
}
False. That’s a good one.
Because the ‘B’ class is loaded in the ‘A’ constructor, ‘B’ statically initializes it’s ‘A’ variable. The singleton object hasn’t been created yet (it hasn’t returned from the original call to the constructor), therefore ‘A’s instance variable is still null. End result is you get two ‘A’ objects in memory.
The better way to do it is like this:
….
private static A instance = new A();
public static A getInstance() {
return instance;
}
….
You still get a “false” printing out, because the references are different. However, only one object is created – this preserves the singleton.
Who would of thought there could be so many nuances to the Java implementation of one of the simplest Java patterns of all? Personally I’m hoping for a Singleton metadata keyword!
Yes, the lazy loading is required. Well, technically, it is “lazy initialization” that is required… the JVM is free to load the classfile into memory at any time, as long as it defers throwing any errors or exceptions until the correct “logical” moment, but none of the static data in the class can be initialized until the class is first accessed.
This is called out in Section 12.4.1 of the Java2 Language Spec, which also defines “first access” as being creation of an instance (“new”), usage of any static method, or access to any non-constant static field. Certain reflective operations also can cause class initialization.
Per the spec, “A class or interface will not be initialized under any other circumstance.”
Section 12.4.1 can be found at http://java.sun.com/docs/books/jls/second_edition/html/execution.doc.html#57946
I am a bit puzzled by this discussion. I would have thought the “guidelines” would be much simpler.
If the design calls for “at most one instance” in the environment use the Singleton pattern.
If the design calls for a class (with possibly multiple instances) closely associated with the enclosing class (or the programmer is too lazy to creat another file) use “static.
A class that is both would be “static Singleton”.
The internal data type distinctions above are possible “propritary” guidelins but somewhat articfical to me.
What am I missing?
one thing about static classes:
i suppose (tell me if i’m wrong!), that you cannot use an InvocationHandler with a Proxy Class on a static class.
this characteristic is useful when you want to intercept method calls on a specific class.
charles.
Reading this today … is this correct:
“To call doStaticMethod we simply invoke it via the class: SingletonClass.doStaticMethod()”
Should not be:
“To call doStaticMethod we simply invoke it via the class: StaticClass.doStaticMethod()”
I mean, not SingletonClass there, but StaticClass?
“To call doSingletonMethod we simply invoke it via an instance of Singleton Class: SingletonClass.getInstance().doSingletonMethod()”
“To call doStaticMethod we simply invoke it via the class: StaticClass.doStaticMethod()”