Singleton + static variables confusion
Hi
I had a question regarding static variables in Singleton classes. Suppose I have a Singleton class like so,
publicclass Singleton{
publicstatic Singleton INSTANCE =new Singleton();
privateint x = 0;
privatestatic String s =null;
private Singleton(){
x = 5;
s ="fjgds";
}
publicint getX(){
return x;
}
public String getS(){
return s;
}
}
Now, this piece of code -
publicstaticvoid main(String[] args){
System.out.println(Singleton.INSTANCE.getX());
System.out.println(Singleton.INSTANCE.getS());
}
gives this output :
5
null
Why is 's' null?
Thanks,
Rajiv
Because static fields are initialised in the order they appear. When INSTANCE is initialized the s field is set to "fjgds", but then the s field's own initialiser sets it back to null.
One reason why it's not a good idea for constructors to have side effects. It's good practise, if you are going to code a singleton this way, to put it's initialiser at the end of the code.
> Leaving the "= null" off the declaration of s would
> have done it too.
This is not a better solution as it may requires to set it null in some applications.
Better declare the string before the INSTANCE as follows:
public class Singleton {
private int x = 0;
private static String s = null;
public static Singleton INSTANCE = new Singleton();
private Singleton() {
x = 5;
s = "fjgds";
}
public int getX() {
return x;
}
public String getS() {
return s;
}
}
It will work perfectly.
If you declare the String after INSTANCE then the following flow will occure:
1. When you declare the INSTANCE public static Singleton INSTANCE = new Singleton();
Then it will initialize the string to fjgds.
2. private static String s = null;
will re-initialize the string to null
>> Leaving the "= null" off the declaration of s would
>> have done it too.
>
>This is not a better solution as it may requires to set it
> null in some applications.
"String s;" sets s to null automatically. All fields are automatically set to null / 0.0 / 0 according to their type before the constructor runs.
I would suggest that as a matter of style a field should not be initialized both in the declaration and in a constructor:
private int x = 0;
private static String s = null;
private Singleton() {
x = 5;
s = "fjgds";
}
To me this raises the suspicion that the programmer is confused: he can't decide whether x should be 0 or 5. Extra code that doesn't do anything is something of a code smell.
>"String s;" sets s to null automatically. All fields are automatically set to null /
>0.0 / 0 according to their type before the constructor runs.
But it rather suprised me to find that, in cases like this, explicity intialisation to null can make a difference (albeit, usually for the worse).
All fields are zero/null before the class intialisation phase actually begins, but if you explicitly set a field to null Java will include code to clear it in <clinit>. So, in this example, had the s field been declared without explicity initialisation then the resuts would have been different.