前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >使用静态内部类来创建单例

使用静态内部类来创建单例

作者头像
丁D
发布2022-08-12 21:42:07
8690
发布2022-08-12 21:42:07
举报
文章被收录于专栏:老铁丁D老铁丁D

我们都知道创建单例模式有懒汉,饿汉。但是我们还可以利用类的加载机制,和静态内部类来创建单例。

静态内部类什么时候加载?

我们知道类的加载时机,是下面5种 1.遇到new、getstatic、setstatic或者invokestatic这4个字节码指令时,对应的java代码场景为:new一个关键字或者一个实例化对象时、读取或设置一个静态字段时(final修饰除外、已在编译期把结果放入常量池的除外)、调用一个类的静态方法时。 2.使用java.lang.reflect包的方法对类进行反射调用的时候,如果类没进行初始化,需要先调用其初始化方法进行初始化。 3.当初始化一个类时,如果其父类还未进行初始化,会先触发其父类的初始化。 4.当虚拟机启动时,用户需要指定一个要执行的主类(包含main()方法的类),虚拟机会先初始化这个类。 5.当使用JDK 1.7等动态语言支持时,如果一个java.lang.invoke.MethodHandle实例最后的解析结果REF_getStatic、REF_putStatic、REF_invokeStatic的方法句柄,并且这个方法句柄所对应的类没有进行过初始化,则需要先触发其初始化。 一开始我是这样想的 静态类和静态对象,静态变量,静态块等等一样,是在类初始化时就被加载。(错)

实际上

代码语言:javascript
复制
public class Outer { 
static { 
System.out.println("load outer class..."); 
} 
//静态内部类 
static class StaticInner { 
static { 
System.out.println("load static inner class..."); 
} 
static void staticInnerMethod() { 
System.out.println("static inner method..."); 
} 
} 
public static void main(String[] args) { 
Outer outer = new Outer(); //此刻其内部类是否也会被加载? 
System.out.println("===========分割线==========="); 
Outer.StaticInner.staticInnerMethod(); //调用内部类的静态方法 
} 
} 
//输出结果 
load outer class... 
==========分割线========== 
load static inner class... 
static inner method... 
//结论 
调用构造方法时,外部类Outer被加载,但这时其静态内部类StaticInner却未被加载。 

扩展:静态内部类创建单例

代码语言:javascript
复制
public class Singleton { 
private Singleton() {} 
static class SingletonHolder { 
private static final Singleton instance = new Singleton(); 
} 
public static Singleton getInstance() { 
return SingletonHolder.instance; 
} 
} 

单例创建多种 https://my.oschina.net/dyyweb/blog/609021

当调用getInstance方法(SingletonHolder.instance)静态内部类才初始化,那么jvm又如何保证静态内部类初始化是线程安全呢? 虚拟机会保证一个类的()方法在多线程环境中被正确地加锁、同步,如果多个线程同时去初始化一个类,那么只会有一个线程去执行这个类的()方法,其他线程都需要阻塞等待,直到活动线程执行()方法完毕。

故而,可以看出INSTANCE在创建过程中是线程安全的,所以说静态内部类形式的单例可保证线程安全,也能保证单例的唯一性,同时也延迟了单例的实例化。

那么,是不是可以说静态内部类单例就是最完美的单例模式了呢?其实不然,静态内部类也有着一个致命的缺点,就是传参的问题,由于是静态内部类的形式去创建单例的,故外部无法传递参数进去。

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2019-06-10 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 静态内部类什么时候加载?
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档