希望长大对我而言,是可以做更多想做的事,而不是被迫做更多不想做的事...... 首页 使用静态内部类来创建单例 丁D 学无止境 2019-06-10 09:01 2887已阅读 单例 静态内部类 摘要本文将介绍如何使用静态内部类来创建单例。 我们都知道创建单例模式有懒汉,饿汉。但是我们还可以利用类的加载机制,和静态内部类来创建单例。 ###静态内部类什么时候加载? 我们知道类的加载时机,是下面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的方法句柄,并且这个方法句柄所对应的类没有进行过初始化,则需要先触发其初始化。 一开始我是这样想的 **静态类和静态对象,静态变量,静态块等等一样,是在类初始化时就被加载。(错)** 实际上 ```js 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却未被加载。 ``` 扩展:**静态内部类创建单例** ```js 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在创建过程中是线程安全的,所以说**静态内部类形式的单例可保证线程安全,也能保证单例的唯一性,同时也延迟了单例的实例化。 ** **那么,是不是可以说静态内部类单例就是最完美的单例模式了呢?其实不然,静态内部类也有着一个致命的缺点,就是传参的问题,由于是静态内部类的形式去创建单例的,故外部无法传递参数进去。** 很赞哦! (0) 上一篇:双层nginx之应用层 下一篇:redis哨兵 目录 点击排行 Elasticsearch6.3.2之x-pack redis哨兵 2019-07-09 22:05 Redis+Twemproxy+HAProxy+Keepalived 2019-07-12 17:20 GC优化策略和相关实践案例 2019-10-10 10:54 JVM垃圾回收器 2019-10-10 10:23 标签云 Java Spring MVC Mybatis Ansible Elasticsearch Redis Hive Docker Kubernetes RocketMQ Jenkins Nginx 友情链接 郑晓博客 佛布朗斯基 凉风有信 MarkHoo's Blog 冰洛博客 南实博客 Rui | 丁D Java研发工程师 生活可以用「没办法」三个字概括。但别人的没办法是「腿长,没办法」、「长得好看,没办法」、「有才华,没办法」。而你的没办法,是真的没办法。 请作者喝咖啡