常见的说法都是说饿汉式单例模式是项目启动的时候加载,会占用项目资源?但是你有没有认识到,这个说法合理吗?
1.准备知识
1.1 JVM类加载机制
一般场景下,new关键字、调用static常量或者方法、反射均会将类初始化。
初始化的过程中,完成静态属性、常量属性的赋值。
1.2 饿汉式单例代码
@Slf4j
public class Singletoneh {
private final static Singletoneh instance = new Singletoneh();
private Singletoneh() {
log.info("==============>我");
}
public static Singletoneh getInstance() {
return instance;
}
public void say() {
System.out.println("【饿汉模式】—实现单例!");
}
}
2. 饿汉式单例真的是项目启动的时候加载的JVM中吗?
不是!正确的说法:饿汉式单例是在类初始化的时候加载到JVM中。
而类初始化的时机:
- new关键字:单例模式构造方法私有化,无法进行调用;
- 静态属性/方法:一般是获取单例instance时调用。即:饿汉式单例模式也是在获取单例的时候才会创建单例对象,且放在JVM中。
所以:饿汉式单例模式和懒汉式单例模式初始化时机大部分相同。
但是饿汉式单例本质上是类初始化单例才加载到JVM中,懒汉式单例是真正调用getInstance方法时单例才加载到JVM中。
饿汉式单例可以在如下场景下,不调用getInstance方法,单例对象加载到JVM虚拟机。
- 饿汉式单例中存在其他静态方法,在调用
static getInstance()
前调用其他静态方法可以完成单例初始化; - 反射调用饿汉式单例的私有构造方法,即可完成初始化;
3. 饿汉式使用final能提前加载吗?
不能!final修饰的常量不会触发类的初始化。