单例模式要求:系统中只能出现一个对象
以下分析全部无视反射,序列化等特殊情况(如果考虑那真没法玩了)
难点:
1.如何保证对象不会被多次创建
2.如何保证线程安全(由问题1导致)
解答:
1.将构造函数设为私有,然后定义一个获取对象的方法或者直接使用public字段,保证获取到的始终是同一个对象
2.饿汉式编程(在类加载的初始化阶段就创建对象),枚举类
答案1:
代码来源netty 4.1.20
public final class ReadTimeoutException extends TimeoutException {
private static final long serialVersionUID = 169287984113283421L;
public static final ReadTimeoutException INSTANCE = new ReadTimeoutException();
private ReadTimeoutException() { }
}
最简单最好用的单例,私有构造函数,公共字段,jvm保证线程安全(jvm会保证多线程同时调用new时对static变量赋值时只进行一次 不明白的参考:深入理解Java虚拟机:JVM高级特性与最佳实践 第2版 7.3.5节初始化)
答案2:
public class Test {
private static Test ourInstance = new Test();
public static Test getInstance() {
return ourInstance;
}
private Test() {
}
}
由idea工具生成的单列,原理和答案1相同,实际使用中,jit会优化内联进行优化,所以不要纠结性能问题
答案3:
直接使用枚举类,这里就不写代码了,直接创建个枚举类,枚举类都是单例的,而且还可以防御反射攻击(绝对没人会去用反射攻击单例这么蛋疼)
总体来说推荐 答案1和答案2,可是,实际上答案3是最好的,它能防御反射和序列化等一切特殊情况,而且effective java书上也推荐,但是枚举并不是很多人都懂,包括我也没仔细研究过,如果你一个人用但是别人不懂那就很尴尬了,所以还是用答案1和答案2好