Java 单例模式的两种高效写法

前言

在Java对象的创建时,单例模式使用尤其多,同时也是个面试必问的基础题。很多时候面试官想问的无非是懒汉式的双重检验锁。但是其实还有两种更加直观高效的写法,也是《Effective Java》中所推荐的写法。

静态内部类(static nested class)

1
2
3
4
5
6
7
8
9
10
11
12
13
public class Singleton {

private static class SingletonHolder {
private static final Singleton INSTANCE = new Singleton();
}

private Singleton() {}

public static final Singleton getInstance() {
return SingletonHolder.INSTANCE;
}

}

这种写法仍然使用JVM本身机制保证了线程安全问题;由于 SingletonHolder 是私有的,除了 getInstance() 之外没有办法访问它,因此它是懒汉式的;同时读取实例的时候不会进行同步,没有性能缺陷;也不依赖 JDK 版本。

枚举 Enum

在《Effective Java》最后推荐了这样一个写法,简直有点颠覆,不仅超级简单,而且保证了现场安全。这里引用一下,此方法无偿提供了序列化机制,绝对防止多次实例化,及时面对复杂的序列化或者反射攻击。单元素枚举类型已经成为实现Singleton的最佳方法。

1
2
3
public enum Singleton {
INSTANCE;
}

对于一个标准的enum单例模式,最优秀的写法还是实现接口的形式:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// 定义单例模式中需要完成的代码逻辑
public interface MySingleton {
void doSomething();
}

public enum Singleton implements MySingleton {
INSTANCE {
@Override
public void doSomething() {
System.out.println("complete singleton");
}
};

public static MySingleton getInstance() {
return Singleton.INSTANCE;
}
}