Why private static field = new Singleton is not la

2020-04-05 09:16发布

I read a lot of articles about Singleton, in most of which authors said that this variation of Singleton in Java:

public class Singleton {
    private static Singleton instance = new Singleton();

    private Singleton() {}
    public static Singleton getInstance() {
        return instance;
    }
}

is NOT LAZY (EAGER then).

But I can't understand why, Singleton() constuctor will be invoked only on Singleton class initialization. I know several reasons, which can trigger class initialization:

  1. Using new with constructor (but in this case constructor is private).
  2. Accessing or setting up static field (here private).
  3. Using static method.
  4. With reflection: Class.forName("Singleton").

So here our object will be created only on using static method getInstance() (it is still LAZY initialization I guess) and with reflection (but reflection can ruin a lot of Singleton variations, except enum maybe).

Maybe I can't see something obvious, explain me please, where was I wrong?

3条回答
太酷不给撩
2楼-- · 2020-04-05 09:31

Basically it's a matter of degrees of laziness. It's lazy in that it won't construct the singleton until the class is initialized, but it's eager in that there could be situations where you want to use the class without initializing the singleton itself.

For example:

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

    private Singleton() {}

    public static Singleton getInstance() {
        return instance;
    }

    public static void sayHello() {
        System.out.println("Hello!");
    }
}

Calling Singleton.sayHello() will instantiate the singleton even if we don't want it to... so it's not as lazy as it could be.

You can get round this using a nested type:

public final class Singleton {
    private Singleton() {}

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

    public static void sayHello() {
        System.out.println("Hello!");
    }

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

Now Singleton.Holder will only be initialized by using the getInstance method. It's lazy and thread-safe with no locking.

In my experience, usually a singleton class's only static method is the getInstance method, in which case they're equivalent (assuming you don't use reflection to initialize the type somehow, for example).

查看更多
霸刀☆藐视天下
3楼-- · 2020-04-05 09:44

It is not lazy because the singeton object is created once the class is loaded.
A lazy Singleton would create the object when it is first used.

查看更多
Rolldiameter
4楼-- · 2020-04-05 09:51

In my point of view, the goal of being Lazy is to control when the instance of the Singleton is created. In this example, there is no control because there is a class variable (static member that is initialized when the class is initialized and not when getInstance() method is called).

That way, there is no control of when the Singleton is created.

But, if you initialize the variable, inside getInstance, you are getting control of when you want the Singleton to be created.

As you said, there are many examples of Singletons. I always try to go for Enums if I need them. You can find examples here: https://connected2know.com/programming/java-singleton-pattern/

查看更多
登录 后发表回答