Reputation: 7616
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?
Upvotes: 4
Views: 98
Reputation: 2155
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.
Upvotes: 1
Reputation: 161
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;
}
}
Upvotes: 0
Reputation: 4060
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.
Upvotes: 4
Reputation: 533510
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.
Upvotes: 0