【单例深思】静态内部类实现详解

静态内部类实现是我个人比较推荐的,其实现如下:

public class Singleton {
    private static class SingletonHolder {
        private static final Singleton INSTANCE = new Singleton();
    }
    private Singleton() {}
    public static final Singleton getInstance() {
        return SingletonHolder.INSTANCE;
    }
}
 
上面实现中,通过声明一个静态内部类 SingletonHolder  来持有单例  INSTANCE   ,在 getInstance() 方法中返回该实例。

我们知道,静态内部类与非静态内部类之间有很大的区别,非静态内部类在编译完成之后会隐含地保存着一个 指向创建它的外围类的 引用,但是静态内部类却没有。这意味着 静态内部类 的创建是不需要依赖于外围类, 它不能使用任何外围类的非static成员变量和方法,某种程度上来说,静态内部类可以当成是一个独立的类。它的初始化和外部类初始化无关。

下面详细介绍一下它是如何解决单例中的各种问题的。

首先,它是如何实现延迟加载的?

由于 INSTANCE  在静态内部类中声明并实例化,在 【单例深思】饿汉式与类加载 中我们知道有且只有5种情况 会引发初始化操作, 初始化阶段是执行类构造器<clinit>()  方法的过程。 <clinit>()  方法是由编译器自动收集类中的所有类变量(static的赋值动作和静态语句块static{})块中的语句合并产生的。因为外部类初始化 不会引发静态内部类 SingletonHolder 的初始化,所以只有真正调用 getInstance() 方法,执行  SingletonHolder. INSTANCE  时,才会引发静态内部类初始化,从而完成实例化。所以,静态内部类实现是延迟加载的。


它如何保证实例化时线程安全?

既然静态内部类初始化可以当成为一个普通类的初始化,根据 【单例深思】饿汉式与类加载 中所描述的类加载过程,可以知道 虚拟机会保证一个类的 <clinit>() 方法在多线程环境中被正确的加锁、同步。所以, 静态内部类实现是在 实例化时是线程安全

在其他方面,由于在读取实例的时候不会进行同步,所以没有性能缺陷;没有使用  volatile ,也不依赖 JDK 版本。

总之,静态内部类实现单例由于编写简单,满足线程安全和延迟加载,无其他明显缺点,是一种在工作中用的比较多的方式。

  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值