单例,即在一个JVM中,最多只有一个这个类的实例。
我们尝试使用几种常见且可用的单例模式,使用下面的测试代码测试直接加载和懒加载
1 2 3 4 5 6 7
| public static void main(String[] args) throws Exception { Class.forName("Singleton");
System.out.println(">>> get instance");
Singleton.getInstance(); }
|
应用场景:
- 直接加载:对于必须加载的单例推荐使用
- 懒加载:对于不必要加载的单例推荐使用
直接用static初始化(直接加载)
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| public class Singleton {
private static final Singleton singleton = new Singleton();
private Singleton() { System.out.println("[Singleton] new instance"); }
public static Singleton getInstance() { return singleton; } }
|
双重判断(懒加载)
应用场景:对于不必要加载的单例推荐使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| public class Singleton {
private static volatile Singleton singleton;
private Singleton() { System.out.println("[Singleton] new instance"); }
public static Singleton getInstance() { if (singleton == null) { synchronized (Singleton.class) { if (singleton == null) { singleton = new Singleton(); } } } return singleton; } }
|
内部类(懒加载)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| public class Singleton {
private Singleton() { }
private static class Holder { private static Singleton singleton = new Singleton(); }
public static Singleton getInstance() { return Holder.singleton; } }
|
内部Enum(懒加载)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| public class Singleton {
private Singleton() { System.out.println("[Singleton] new instance"); }
public static Singleton getInstance() { return Instance.INSTANCE.value; }
private enum Instance { INSTANCE, ;
private Singleton value = new Singleton(); } }
|
直接Enum(直接加载)
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| public enum Singleton { INSTANCE, ;
Singleton() { System.out.println("[Singleton] new instance"); }
public static Singleton getInstance() { return Singleton.INSTANCE; } }
|
注意
- 构造函数全为
private的类不能被继承,因为子类不能实例化父类。所以单例类不能被继承。