-
The problem
There are two common ways to implement Singleton, both by making the constructor private and then exporting it to a public static field. One way is through static final public member variables:
public class Singleton{ public static final Singleton instance = new Singleton(); private Singleton(){ ...... }}Copy the code
** Disadvantages: ** This way, you can change the private properties of the constructor by reflection, creating multiple instance objects, which requires a logical judgment in the constructor that the second instance is not allowed.
Alternatively, we can export static methods to public:
class Singleton{ private static final Singleton instance = new Singleton(); public static Singleton getInstance(){ return instance; } private Singleton(){}; } Copy the code
But there is still a problem with the reflex mechanism in the first method. Another problem with the above two approaches is that it is not enough to simply add “Implement Serializable” to the name when implementing the Singleton class serialization. To maintain and guarantee the Singleton, it is necessary to declare all instances transient and provide a readResolve method. Otherwise, a new instance will be created each time the deserialization is performed, and the following code will be added:
// readResolve method to preserve singleton property private Object readResolve() { // Return the one true Elvis and let the garbage collector // take care of the Elvis impersonator return INSTANCE; }Copy the code
So, what’s the easiest, safest way to build a Singleton?
-
To solve
The safest and most reliable way to implement a Singleton is to write an enumeration element containing a single element:
public enum Elvis { INSTANCE; public void leaveTheBuilding() { ... }}Copy the code
This approach is simpler, provides a serialization mechanism for free, absolutely prevents multiple instantiations (guaranteed by Enum), and is unique even in the face of complex serialization or deserialization or reflection attacks. This has become the best way to implement Singleton.
-
conclusion
However, when you need to create a Singleton, you can use enumerations, which are both concise and serial-safe and reflective