What is the best/correct way to create a singleton class in java?
One of the implementation I found is using a private constructor and a getInstance() method.
package singleton; public class Singleton { private static Singleton me; private Singleton() { } public static Singleton getInstance() { if (me == null) { me = new Singleton(); } return me; } }
But is implementation fails in the following test case
package singleton; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; public class Test { /** * @param args * @throws NoSuchMethodException * @throws SecurityException * @throws InvocationTargetException * @throws IllegalAccessException * @throws InstantiationException * @throws IllegalArgumentException */ public static void main(String[] args) throws SecurityException, NoSuchMethodException, IllegalArgumentException, InstantiationException, IllegalAccessException, InvocationTargetException { Singleton singleton1 = Singleton.getInstance(); System.out.println(singleton1); Singleton singleton2 = Singleton.getInstance(); System.out.println(singleton2); Constructor<Singleton> c = Singleton.class .getDeclaredConstructor((Class<?>[]) null); c.setAccessible(true); System.out.println(c); Singleton singleton3 = c.newInstance((Object[]) null); System.out.println(singleton3); if(singleton1 == singleton2){ System.out.println("Variable 1 and 2 referes same instance"); }else{ System.out.println("Variable 1 and 2 referes different instances"); } if(singleton1 == singleton3){ System.out.println("Variable 1 and 3 referes same instance"); }else{ System.out.println("Variable 1 and 3 referes different instances"); } } }
How to resolve this?
Thank you
To create the singleton class, we need to have static member of class, private constructor and static factory method. Static member: It gets memory only once because of static, itcontains the instance of the Singleton class. Private constructor: It will prevent to instantiate the Singleton class from outside the class.
Eager initialization: In eager initialization, the instance of Singleton Class is created at the time of class loading, this is the easiest method to create a Singleton class. By making the constructor as private you are not allowing other class to create a new instance of the class you want to create the Singleton.
The most popular approach is to implement a Singleton by creating a regular class and making sure it has: A private constructor. A static field containing its only instance. A static factory method for obtaining the instance.
Example of singleton classes is Runtime class, Action Servlet, Service Locator. Private constructors and factory methods are also an example of the singleton class.
As per the comment on your question:
I've a properties file containing some keys value pairs, which is need across the application, that is why I was thinking about a singleton class. This class will load the properties from a file and keep it and you can use it from anywhere in the application
Don't use a singleton. You apparently don't need one-time lazy initialization (that's where a singleton is all about). You want one-time direct initialization. Just make it static and load it in a static initializer.
E.g.
public class Config { private static final Properties PROPERTIES = new Properties(); static { try { PROPERTIES.load(Thread.currentThread().getContextClassLoader().getResourceAsStream("config.properties")); } catch (IOException e) { throw new ExceptionInInitializerError("Loading config file failed.", e); } } public static String getProperty(String key) { return PROPERTIES.getProperty(key); } // ... }
If you are using reflection to pierce encapsulation, you should not be surprised when behavior of your class is altered in incorrect ways. Private members are supposed to be private to the class. By using reflection to access them you are intentionally breaking the behavior of the class, and the resultant "duplicate singleton" is expected.
In short: Don't do that.
Also, you might consider creating the singleton instance in a static constructor. Static constructors are synchronized and will only run once. Your current class contains a race condition -- if two separate threads call getInstance()
when it has not been previously called, there is a possibility that two instances will be created, one of them being exclusive to one of the threads, and the other becoming the instance that future getInstance()
calls will return.
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