Linh
Linh

Reputation: 61009

The instantiation happened before getInstance() or when getInstance()?

I'm following this tutorial for create Singleton and the owner have comment when the method below http://www.journaldev.com/1377/java-singleton-design-pattern-best-practices-examples

public class EagerInitializedSingleton {

    private static final EagerInitializedSingleton instance = new EagerInitializedSingleton();

    //private constructor to avoid client applications to use constructor
    private EagerInitializedSingleton(){}

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

If your singleton class is not using a lot of resources, this is the approach to use. But in most of the scenarios, Singleton classes are created for resources such as File System, Database connections etc and we should avoid the instantiation until unless client calls the getInstance method.

The Problem Is:

They say we should avoid the instantiation until unless client calls the getInstance method BUT as I know in this code the instantiation (of object instance) always happened when class EagerInitializedSingleton load, and EagerInitializedSingleton just only load when we call EagerInitializedSingleton.getInstance()
=> The instantiation will happened on time with getInstance() and never before getInstance()

Reference:

Static variables are initialized only once , at the start of the execution(when the Classloader load the class for the first time) . (from https://stackoverflow.com/a/8704607/5381331)

So when are classes loaded?
There are exactly two cases:
- when the new bytecode is executed (for example, FooClass f = new FooClass();)
- and when the bytecodes make a static reference to a class (for example, System.out) (from http://www.javaworld.com/article/2077260/learn-java/learn-java-the-basics-of-java-class-loaders.html)

Am I wrong or correct. Please give me some sugestion.

Upvotes: 1

Views: 368

Answers (3)

rajuGT
rajuGT

Reputation: 6414

They say we should avoid the instantiation until unless client calls the getInstance method

The solution is lazy loading. From wikipedia, Initialization-on-demand holder idiom

When the class Something is loaded by the JVM, the class goes through initialization. Since the class does not have any static variables to initialize, the initialization completes trivially. The static class definition LazyHolder within it is not initialized until the JVM determines that LazyHolder must be executed. The static class LazyHolder is only executed when the static method getInstance is invoked on the class Something, and the first time this happens the JVM will load and initialize the LazyHolder class.

public class Something {
  private Something() {}

  private static class LazyHolder {
    private static final Something INSTANCE = new Something();
  }

  public static Something getInstance() {
    return LazyHolder.INSTANCE; 
  }
}

Upvotes: 1

Shadov
Shadov

Reputation: 5591

I think the problem is when a class gets loaded without the need to get the instance, but for some other reason. You assume that class will be used the first time when user will want to get an instance of that singleton, but it may happen for some other reason, he may just call a class loader for something, or use some 3rd party software to validate a class, anything that comes to mind that involves loading a class but not getting an instance of a singleton.

Upvotes: 1

Mena
Mena

Reputation: 48434

In this case with that specific code, you are probably correct.

However, if you had static methods of EagerInitializedSingleton, or static non-final members of EagerInitializedSingleton referenced somewhere in your code base prior to the invocation of getInstance, the instance variable of EagerInitializedSingleton would initialize.

Same with a reflective invocation of Class.forName on your EagerInitializedSingleton class.

Note (and forgive the obvious here) that there are alternative ways of declaring a singleton, including lazy-initialization or enums.

Upvotes: 2

Related Questions