I have this singleton I'm trying to use, but getInstance can apparently return null:
class Singleton {
public static final String K_LEVEL = "level";
static Singleton instance = new Singleton();
private int level;
static Singleton getInstance() {
return instance;
}
int getLevel() {
return level;
}
void incrementLevel() {
System.out.println("LEVEL INCREASED TO " + ++level);
}
void addToLevel(int x) {
for(int i=0;i<x;i++)
incrementLevel();
}
}
class A {
public static void main(String[] args) {
Singleton s = Singleton.getInstance();
Integer i = Integer.getInteger(Singleton.K_LEVEL);
s.addToLevel(i);
}
}
I heard implementing singletons in Java is very hard and prone to race conditions. Is my singleton pattern implemented wrong? I recently changed my code to look like this, and now getInstance returns null sometimes. Why?
$ java A -Dlevel=1
Exception in thread "main" java.lang.NullPointerException
at A.main(A.java:29)
the instance on a Singleton could never become null, except for when the app would be completely restarted (in which case it should by recreated by my application class).
A common mistake with that implementation is to neglect synchronization, which can lead to multiple instances of the singleton class.
When the singleton class is loaded, inner class is not loaded and hence doesn't create object when loading the class. Inner class is created only when getInstance() method is called. So it may seem like eager initialization but it is lazy initialization.
This is easier with a dependency injection framework, but works without, too. If you do it like that, you declare the dependency, and you can actually test your Something and mock the single instance if necessary without all the problems related to the singleton pattern.
There is nothing wrong with your Singleton. There are no concurrency problems because this is not multithreaded code.
You were thinking s
was null, but it is really i
that was null.
Since addToLevel
takes an int
as a parameter, the Integer i
was autounboxed (implicitly converted from Integer
to int
), but since i
was null
, NullPointerException
was thrown. Autounboxing throws NullPointerException
when the value being coverted is null
.
The reason Integer.getInteger(Singleton.K_LEVEL)
returned null
is because you did java A -Dlevel=1
as opposed to java -Dlevel=1 A
. The latter is the correct syntax.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With