4

I have a Singleton Logger class.

public class Logger {
  public static Logger INSTANCE = new Logger();

  private Logger() {
    ...
  }
}

I want to log in my constructor that a new instance is created. So my code looks like:

public class MyClass {
  public MyClass() {
    Logger.INSTANCE.log("MyClass created");
    ...
  }
}

I am wondering if this could break static instances of MyClass. For instance, if I have:

public class MyOtherClass {
  private static MyClass myClass = new MyClass();
  ...
}

I fear that this could cause a problem due to undefined order of initialization of static variables. So if myClass is initialized before Logger.INSTANCE is, then the construction of myClass will crash. Is there some mechanism to prevent this from happening or is using static variables in a constructor inherently dangerous? Is there any way to prevent users from creating static instances of MyClass in such a case?

2
  • If you must use a singleton pattern, the instance itself shouldn't be available. It should he wrapped in a method. Commented Aug 2, 2015 at 8:24
  • Note that in this case, your instance variable should be final and either private or protected. Commented Aug 2, 2015 at 8:34

4 Answers 4

4
public class Logger {
  public static Logger INSTANCE = new Logger();

  private Logger() {
    ...
  }
}

Is syntactic sugar for

public class Logger {
  public static Logger INSTANCE;
  static {
      INSTANCE = new Logger();
  }

  private Logger() {
    ...
  }
}

A static block sets up static members of the class, and is guaranteed to run before your class is used.

Sign up to request clarification or add additional context in comments.

Comments

1

I recommend you to wrap your Logger.INSTANCE like in classic singleton:

public class Logger{

  private static Logger logger;

  private Logger(){

  }

  public static Logger getInstance(){
     if(logger==null){
         logger = new Logger();
     }
    return logger;
  }

}

This way when you will call Logger.getInstance() you will never get null.

If you need thread safe singleton:

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

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

This way you also will never get null because by default Logger will be initialized before class where it will be used, because in this case it will be dependency of other class.

1 Comment

Also, lazy loading isn't an explicit requirement.
0

So if myClass is initialized before Logger.INSTANCE is, then the construction of myClass will crash.

You can't initialise a class until all the classes it depends on have been initialised.

Is there some mechanism to prevent this from happening or is using static variables in a constructor inherently dangerous?

You can't use a class before it has been initialised (unless you call it in the initialisation code)

Is there any way to prevent users from creating static instances of MyClass in such a case?

You can't construct an instance of a class, until the classes it uses have been initialised.

Comments

0

No need to worry about breaking anything, JVM will ensure the correct order of construction. However there is a risk multiple instances are created if accessed my many threads. Improve the code my declaring the singleton as final and using an static method to access:

public class Logger {
  private static final Logger INSTANCE = new Logger();

  private Logger() {}

  public static Logger getInstance() {
      return INSTANCE;
  }
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.