1
votes

I have code like this:

class Singleton {

    private static final Singleton INSTANCE = new Singleton();

    private Singleton() {
        System.out.println("Singleton constructed.");
    }

    public static Singleton getInstance() {
        return INSTANCE;
    }

}

When we don't have any other static method that getInstance, is this singleton lazy initializated? As far as I know class is initialized only in some cases, like:

  1. An Instance of class is created using either new() keyword or using reflection using class.forName(), which may throw ClassNotFoundException in Java.
  2. An static method of Class is invoked.
  3. An static field of Class is assigned.
  4. An static field of class is used which is not a constant variable.
  5. If Class is a top level class and an assert statement lexically nested within class is executed.

(Surce: http://javarevisited.blogspot.com/2012/07/when-class-loading-initialization-java-example.html#ixzz4IjIe2Rf5)

So when the only static method is getInstance and constructor is private there is no possibility to initialize Singleton class in any other way than using getInstance method (apart from reflection). So the object is created only when we need it so it's a lazy initialization, right? Or maybe I missed something?

5

5 Answers

2
votes

You mentioned static methods and private constructor. Add another static field, something like:

static int NUMBER = 13;

in your Singleton class. And in the main method of other class:

System.out.println(Singleton.NUMBER);

then, you will see that your Singleton is not lazy initialized.

BUT, when your field is static FINAL:

static final int NUMBER = 13;

the Singleton is lazy initialized.

What is more, when you add static and non-static initialization blocks in your Singleton class:

{
    System.out.println("non-static");
}

static {
    System.out.println("static");
}

the order is: non-static, private constructor and then static, because you are instatiating an object as a value of static field. So, it is very tricky :)

In summary, in some cases your Singleton may be considered as lazy initialized but it is not in general.

2
votes

It's initialized immediately so no, it's not. Typically a lazy initialization means you initialize it when you try to actually retrieve it but the field isn't initialized yet.

Lazy initialization is not about the class initializing -- it's about the field that's contained in it. In your case as soon as the class is loaded, the field will be initialized immediately.

Your example adapted to use lazy initialization:

class Singleton {
    private static Singleton INSTANCE;

    private Singleton() {
        System.out.println("Singleton constructed.");
    }

    public static Singleton getInstance() {
        if(INSTANCE == null) {
            INSTANCE = new Singleton();
        }
        return INSTANCE;
    }
}

This will only construct the singleton when it is actually requested and not just when the Singleton class is loaded in memory. In your situation, if it is loaded in memory then its static fields would be initialized (including your singleton field).

1
votes

EDIT: I was wrong. A class is NOT loaded just by referencing it, like below:

System.out.println(Singleton.class); 

A class is loaded by the class loader as soon as an instance is created, a static member is referenced, or by loading it programmatically:

Class<?> clazz = Class.forName("Singleton"); // fully qualified classname

The above statement causes the class to be loaded, and all static members and blocks will be processed in order of appearance in the class. In your example class this will cause the INSTANCE variable to be initialized (and the message to be printed to System.out). This proves that your approach does not guarantee lazy loading.

A better way to implement a lazy loading singleton is with the Singleton holder pattern:

class Singleton {

    private static class Holder {
        private static final Singleton INSTANCE = new Singleton();
    }

    private Singleton() {
        // hide constructor
    }

    public static Singleton getInstance() {
        return Holder.INSTANCE;
    }

}
0
votes

No, it is not lazy initialized. Lazy mean on first call or never. In your case it is not on first call.

You can pass lazy initialization problem to SingletonHolder class. It will be initialized on first getInstance call.

public class Singleton {
    private Singleton() {}

    private static class SingletonHolder {
        private static final Singleton instance = new Singleton();
    }

    public static Singleton getInstance() {
        return SingletonHolder.instance;
    }
}
0
votes

If you're using .NET 4 (or higher), John Skeet recommends you do the following:

You can use the System.Lazy type to make the laziness really simple. All you need to do is pass a delegate to the constructor which calls the Singleton constructor - which is done most easily with a lambda expression.

public sealed class Singleton
{
    private static readonly Lazy<Singleton> lazy = new Lazy<Singleton> (() => new 
                            Singleton());

    public static Singleton Instance { get { return lazy.Value; } }

    private Singleton()
    {
    }
 }

It's simple and performs well. It also allows you to check whether or not the instance has been created yet with the IsValueCreated property, if you need that.

The code above implicitly uses LazyThreadSafetyMode.ExecutionAndPublication as the thread safety mode for the Lazy. Depending on your requirements, you may wish to experiment with other modes.