Typically Java singletons are created using double-checked locking (i.e. check if the singleton instance is null, only if it is, go into synchronized code, check if null again and create instance). However, a more elegant way of doing this is to use static code blocks, which are also thread safe. For example:
public class ourSingleton{
public static ourSingleton INSTANCE;
private static String demo;
private ourSingleton(){
demo = "ourSingleton"; // an example of initializing a variable
this.INSTANCE = this;
System.out.println("init done");
}
static { // static code block
new ourSingleton();
}
public void printDemo(){
System.out.println(this); // show that same instance of class is used
System.out.println(demo); // get access to the initialized variable
}
}
// [...]
// note that now ourSingleton.INSTANCE can't be null due to the static code block, eliminating
// the need for the typical double-check locking
ourSingleton demo1 = ourSingleton.INSTANCE;
ourSingleton demo2 = ourSingleton.INSTANCE;
demo1.printDemo();
demo2.printDemo();
/*
outputs:
"
init done <---- init only called once
ourSingleton@5594a1b5 <---- same output for both instances of singleton
ourSingleton
ourSingleton@5594a1b5
ourSingleton
"
*/
Typically Java singletons are created using double-checked locking (i.e. check if the singleton instance is null, only if it is, go into synchronized code, check if null again and create instance). However, a more elegant way of doing this is to use static code blocks, which are also thread safe. For example:
In kotlin this is even easier by using an
object
: