-1

We all know this old well-known idiom of lazy-init singleton:

public class Singleton {
    private static volatile Singleton instance;

    private Singleton()
    {
        // init...
    }

    public static Singleton getInstance()
    {
        if (instance == null) {
            synchronized (Singleton.class) {
                if (instance == null) {
                    instance = new Singleton();
                }
            }
        }

        return instance;
    }
}

However, the following idiom is also lazy, by nature, because the instance will be init only when the class is first accessed, handled by the class loader:

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

    private Singleton()
    {
        // init..
    }

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

So the question is, why would we want to use the first example and not the second? (not referring to the fact that it's better to use frameworks such as spring for managing your objects' life cycle..)

Even if you hold a reference to the singleton in another class, like this:

public class Holder {
   private int member1;
   private int member2;
   private Singleton myService = Singleton.getInstance();

}

The singleton will be created when the Holder class is loaded, regardless of which approach we take

Any insights? thanks

paranoidAndroid
  • 523
  • 5
  • 12
  • The second way described isn't lazy, as the instance is initialized when the class is references. For "true" laziness the instance should be initialized when the instance itself is used, not just when the class is loaded. – Kayaman Jan 11 '18 at 20:11
  • Why mark my question as duplicate? I am not searching for the most efficient way. This is a just a theoretical question. As for my understanding, there is no difference between the two. You are wrong because the class will get loaded only when you use it, i.e. call a method on it or access a member. The only case that is not covered, is the one Neil mentioned – paranoidAndroid Jan 11 '18 at 20:14
  • I've had this same discussion too many times (often with the "you are wrong" claims from inexperienced people). Your understanding is wrong, and the duplicate contains nicely all the different singleton patterns, including the modern `enum` one and the older inner class lazy loader. There's nothing to discuss here really. – Kayaman Jan 11 '18 at 20:21
  • ok, can you elaborate why am i wrong? If you just declare a member of the class Singleton in another class, it won't get loaded until you actually use the class, i.e. call a method, access a member. If this is wrong... – paranoidAndroid Jan 11 '18 at 20:27
  • This is the pattern you are looking for: https://en.wikipedia.org/wiki/Initialization-on-demand_holder_idiom . – jtahlborn Jan 11 '18 at 21:23
  • @paranoidAndroid because it doesn't fulfill the requirement for the "true" laziness for singletons. Lazy singleton **must** be initialized when **instance** is needed, no earlier. The class **can** be loaded before that. Your lazy singleton can be defeated by `System.out.println(Singleton.class.getName());`. Even most eager singletons are lazy if given suitable constraints, but that's just "conditionally lazy". Hell, I can say that `new Object();` is a lazy singleton, given extremely tight constraints on further code. – Kayaman Jan 12 '18 at 06:29
  • Like I said in my deleted answer, singleton pattern has the lowest ratio of usefulness vs. discussion IMO. People keep coming up with the "dcl is broken" argument from years back, inventing their own "clever" ways, and generally just wasting time on something that's essentially the first design pattern they've learned at school. The linked duplicate has a **lot** of discussion, so I rather dupehammer these questions than go through the same things over and over. If you think you have something to add, please put it to the duplicate as a comment or answer. – Kayaman Jan 12 '18 at 06:32
  • thank you, it is understood now (the example you gave is straight forward). BTW as I mentioned before, I dont think this pattern is good or useful. This is just a theoretical question. I prefer using a framework like Spring to mange my objects' life cycle – paranoidAndroid Jan 13 '18 at 18:04

1 Answers1

0

What about something like this?

public class Singleton {
    ...
    public static int getSomeStaticInfo() { return 42; }
    ...
} 

public class Holder {
    private int member1;
    private int member2 = Singleton.getSomeStaticInfo();
    private Singleton myService;

    public void init() {
        myService = Singleton.getInstance();
    }
}

The behavior of when your singleton is initialized differs between the two versions. This is where version 1 exhibits the correct (in terms of what we'd want when we say "lazy") behavior. Just because you load the class, doesn't mean you want it initialized.

Neil Locketz
  • 4,228
  • 1
  • 23
  • 34