Java单例---静态内部类

之前写过一篇双重锁校验单例 ,这是延迟加载的一种单例模式,俗称懒汉模式,这次写一个静态内部类的单例,这个写法天生线程安全,并且引出反射攻击,废话不多说,上代码:

java 复制代码
public class StaticInnerClass {

    private static class InnerClass{
        private static StaticInnerClass staticInnerClass = new StaticInnerClass();
    }

    public static StaticInnerClass getInstance(){
        return InnerClass.staticInnerClass;
    }

    private StaticInnerClass(){
    	
    }

}

这种静态内部类的实现方式,它主要原理是:加载一个类时,其内部类不会同时被加载。一个类被加载,当且仅当其某个静态成员(静态域、构造器、静态方法等)被调用时发生 ,也就是说内部类:InnerClass只有我们调用getInstance()的时候才会被加载。

那么这个写法为什么线程安全呢?原因可以在《深入理解Java虚拟机》这本书的第七章7.3.5小节找到答案,这里摘要出主要原因,大家有兴趣可以自己去看看书:

  • 虚拟机会保证一个类的< clinit>()方法在多线程环境中被正确的加锁、同步,如果多个线程同时去初始化一个类,那么只会有一个线程去执行这个类的< clinit>()方法,其他线程都需要阻塞等待,直到活动线程执行< clinit>()方法完毕。如果在一个类的< clinit>()方法中有耗时很长的操作,就有可能造成多个进程阻塞(需要注意的是,其他线程虽然会被阻塞,但如果执行< clinit>()方法的那条线程退出< clinit>()方法后,其他线程唤醒之后不会再次进入< clinit>()方法。同一个类加载器下,一个类型只会被初始化一次),在实际应用中这种阻塞旺旺是很隐蔽的。

这就是他线程安全的原因,通俗的说就是这个静态内部类只能同时有一个线程去初始化它,其他的被阻塞,如果一个线程初始化了这个静态内部类,那么其他的就不会再去初始化了。

那么上面这个写法就真的能保证这个类的实例在任何情况下都只有一个吗?其实是不行的,通过反射的方式,就可以修改这个类的私有构造器权限,然后创建出一个这个类的实例,这个在下一篇博客里面写。

个人浅薄理解,欢迎补充

相关推荐
我命由我123452 小时前
Android Studio - Android Studio 自定义预览尺寸
android·java·ide·java-ee·android studio·android-studio·android runtime
mCell2 小时前
你以为短链接只是 Hash + 301/302?
后端·算法·架构
怕浪猫3 小时前
现在的"AI 原生应用"热潮,恰恰证明了大多数产品需求本身就是个草台班子
面试
咖啡八杯3 小时前
GoF设计模式——迭代器模式
java·后端·设计模式·迭代器模式
AIGS0013 小时前
企业AI落地的关键认知:向量空间JBoltAI的本体语义平台
java·人工智能·人工智能ai大模型应用
KaMeidebaby4 小时前
卡梅德生物技术快报|抗体亲和力成熟工业化调控新机制:差异性浆细胞增殖工艺优化思路
java·开发语言·人工智能·算法·机器学习·架构·spark
醉城夜风~5 小时前
Java详解经典算法题:接雨水(三种实现方案+原理剖析)
java·开发语言·算法
TPBoreas6 小时前
MySQL性能优化面试全攻略
mysql·面试·性能优化
数智化转型推荐官6 小时前
2026统一身份管理系统五大发展趋势解读
java·运维·微服务
看菜鸡互7 小时前
探索用 SlideML 让大模型生成 PPT 的实验方法
java·运维