单例设计模式中类加载顺序

加载完类后,类的初始化就会发生,如果是对一个类的主动使用就会初始化对象,对类的被动使用不会对类进行初始化,比如final修饰的静态变量如果能在编译时就确定变量的取值,会被当做常量,作为对一个类的被动使用不会导致类的初始化。

以下情况类被初始化

  • 最常见的就是直接创建一个类的实例(new 一个对象),有可能导致ClassNotFoundException。
  • 调用一个类的静态方法,public static XXX();
  • 调用一个类的静态变量并且它不是常量或者是对静态变量进行赋值;
  • 调用Java API的反射,例如动态加载一个类Class.forName();
  • 初始化一个类的子类会首先初始化一个类的父类;
  • 启动包含main()的类;
  • 在顶层类中执行assert语句;

类初始化的一些规则:

  • 类从顶至底的顺序初始化,所以声明在顶部的字段的早于底部的字段初始化;
  • 超类早于子类和衍生类的初始化;
  • 如果类的初始化是由于访问静态域而触发,那么只有声明静态域的类才被初始化,而不会触发超类的初始化或者子类的初始化,即使静态域被子类或子接口或者它的实现类所引用;
  • 接口初始化不会导致父接口的初始化;
  • 静态域的初始化是在类的静态初始化期间,非静态域的初始化时在类的实例创建期间,这意味着静态域初始化在非静态域之前;
  • 非静态域通过构造器初始化,子类在做任何初始化之前构造器会隐含地调用父类的构造器,他保证了父类非静态或实例变量初始化早于子类;

  • 我们的对象初始化的时间是Singleton object1= Singleton.getInstance();中的Singleton.getInstance(),当这个方法执行的时候,要做这几件事情,

  • 首先就是看一下自己有没有父亲,如果有先初始化父亲的静态变量,然后初始化自己的静态变量private static Singleton singleton=new Singleton();

  • 之后初始化父类的构造器中的变量,最后初始化自己构造器之中的方法,到了最后一切进行完毕,才开始调用Singleton.getInstance()方法,这个时候singleton早就有对象了,因此将对象返回。因此当打印出“开始初始化对象”的时候(执行自身构造器方法),其实作为静态变量的singleton早就已经初始化成功了,这里有一定的误导之嫌,望读者注意。

  • 那么到底要不要在private static Singleton singleton=new Singleton();中加final呢?其实理解到这种程度我们就知道无所谓了,因为是私有,只有自己能使用,定义final想把自己当做编译时就能处理的常量,可是又使用了new关键字,就失去了这个作用了,因此有和没有一点关系都没有,当然这是不考虑反射的时候。

    2.3、那么在有的教材中还有一些单例方法,比如称我们这里的方法为饿汉式方法,而其他的又懒汉式方法,懒汉式方法总是会出现这样或那样的问题的,因为考虑到了多线程机制,实现起来比较麻烦,并且还会出现问题,就算是使用了一定的解救办法(同步、加锁、双重判断)的办法,性能还是被损耗了,因此懒汉式方法的弊端非常大,但是因为‘懒’,所以可以晚一点加载,占用的内存就会晚一点,这样可以为之前的进程节省空间,这也是从辩证法角度看问题的必然结果,凡事有利必有弊。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值