- 单例类只能有一个实例;
- 单例类必须自己创建自己的唯一实例;
- 单例类必须给所有其他对象提供这一实例。
// 懒汉式单例类,在第一次调用的时候实例化自己
public class Singleton {
private Singleton() {
}
private volatile static Singleton singleton = null; // 声明成 volatile
// 静态工厂方法
public static Singleton getInstance() {
if (singleton == null) {
synchronized (Singleton.class) {
if (singleton == null) {
singleton = new Singleton();
}
}
}
return singleton;
}
}
// 饿汉式单例类,在类初始化时,已经自行实例化
public class Singleton {
private Singleton() {
}
private static final Singleton single = new Singleton();
// 静态工厂方法
public static Singleton getInstance() {
return single;
}
}
但当单例类当实现了 Serializable
接口后,反序列化时单例会被破坏,此时需要重写 readResolve
,才能保证其反序列化依旧是单例,如下所示:
private Object readResolve() throws ObjectStreamException {
return single;
}
public class Singleton {
private static class LazyHolder {
private static final Singleton INSTANCE = new Singleton();
}
private Singleton() {
}
public static Singleton getInstance() {
return LazyHolder.INSTANCE;
}
}
public enum Singleton {
INSTANCE;
public void whateverMethod() {
}
}
枚举类是 Effective Java 作者 Josh Bloch 提倡的方式,它不仅能避免多线程同步问题,而且还能防止反序列化重新创建新的对象,可谓是很坚强的壁垒,不过在实际工作中,我很少看见有人这么写过。
工作中我基本都是用内部静态类,具有懒加载和线程安全的效果,如果涉及到反序列化创建对象时我会试着使用枚举的方式来实现单例,如果每次书写嫌麻烦的话,可以在 Android Studio 中设置 Preferences -> Editor -> Live Templates
来快速创建出自己需要的单例。
我正在打造一个帮助 Android 开发者们拿到更好 offer 的面试库————安卓 offer 收割基,欢迎 star,觉得不错的可以持续关注,有兴趣的可以一起加入进来和我一同打造。