饿汉式单例模式
public class Singleton { private Singleton() {} private static final Singleton single = new Singleton(); //静态工厂方法 public static Singleton getInstance() { return single; } }
静态内部类实现的懒汉式单例模式
public class Singleton { private static class LazyHolder { private static final Singleton INSTANCE = new Singleton(); } private Singleton (){} public static final Singleton getInstance() { return LazyHolder.INSTANCE; } }
第一种方式是饿汉式单例模式,比较容易理解的,即类在加载后就实例化了。
第二种方式是懒汉式单例模式,且使用了静态内部类实现。可能很多人一开始看到的时候会觉得,使用这种方式的单例模式也是在类加载后就实例化了,其实不然,如果我们在以上两种单例模式的构造器中随意加入一行打印字符串的代码,然后加载一下以上两个类就会发现区别。
例如:都将构造器改为
private Singleton(){ System.out.println("init"); }
添加测试使用的main方法
public static void main(String[] args) { Singleton s = getInstance(); }
使用debug模式,在Singleton s = getInstance();一行处打上断点,并执行main方法。由于打了断点,所以执行main方法后会在执行Singleton s = getInstance();前停止,但此时第一种方式的单例模式打印出了“init”字样,而第二种方式单例模式并未打印,直到执行Singleton s = getInstance();一行代码后才打印“init”字样。也就说明了第一种是饿汉式,第二种是懒汉式。
关于使用静态内部类实现的单例模式为什么是懒汉式的,其实和静态内部类有关。
内部类分为对象级别(非静态内部类)和类级别(静态内部类),类级内部类指的是,有static修饰的成员变量的内部类。如果没有static修饰的成员变量的内部类被称为对象级内部类。
类级内部类相当于其外部类的static成员,它的对象与外部类对象间不存在依赖关系,相互独立,因此可直接创建。而对象级内部类的实例,是必须绑定在外部对象实例上的。
类级内部类只有在第一次被使用的时候才被会装载。