magpiebrain

Sam Newman's site, a Consultant at ThoughtWorks

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:

  1. If the only data it uses that isn’t passed in is all constant (read: final) data, its a static class
  2. If it has NO internal data at all, its a static class
  3. If it has non-constant data and it only makes sense to have one of them, then its a Singleton
  4. 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 🙂

Advertisements

20 Responses to “Of Singletons and Static classes”

  1. adam connor

    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).

    Reply
  2. fx

    But your staticData object can be an interface, so it gives you the flexibility you need when implementing instance()

    Reply
  3. Jed Wesley-Smith

    btw, the lazy loading of a static is unnecessary, the VM will only construct a static member when it is first accessed anyway.

    Reply
  4. Payton Quackenbush

    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.

    Reply
  5. Sam Newman

    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 🙂

    Reply
  6. Jay

    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.

    Reply
  7. Sam Newman

    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.

    Reply
  8. DaveH

    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)

    Reply
  9. Wesley R. Tarpley

    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!

    Reply
  10. Sam Newman

    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!

    Reply
  11. Weiqi Gao

    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);
    }
    }

    Reply
  12. damien

    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.

    Reply
  13. Sam Newman

    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!

    Reply
  14. Doug

    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

    Reply
  15. Tom Thomason

    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?

    Reply
  16. charles gay

    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.

    Reply
  17. TaQ

    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?

    Reply
  18. Prateek Kathpal

    “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()”

    Reply

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Basic HTML is allowed. Your email address will not be published.

Subscribe to this comment feed via RSS

%d bloggers like this: