zoukankan      html  css  js  c++  java
  • 接口初始化规则与类加载器准备阶段和初始化阶段的重要意义分析

    接口初始化规则:

    在之前的例子中都是围绕类来进行的,这次来看一下接口的初始化相关的东东,直接新建一个例子:

    此时编写main方法去调用接口里面的字段:

    照着之前【http://www.cnblogs.com/webor2006/p/8835953.html】类的例子来看,如果主动使用了子类那其它的父类也会被初始化,而调用静态字段时它的类也就会被主动使用,回忆一下:

    那对于接口,里面没法给static静态代码块来验证该类是否初始化了,那如何整呢?这时先运行一下:

    此时会生成字节码文件,然后将MyParent5的字节码文件给删掉,再运行:

    所以这里说明一个问题:当一个接口在初始化时,并不要求其父接口都完成了初始化。

    那如果将MyChild5的字节码文件也删掉呢?看结果:

    同样能运行,那不跟之前做的编译期常量放在常量的类似,呃,常量?问题是在接口中木有声明为final呀:

    那加上呗:

    标灰了,很显然对于接口而言定义的字段都是常量的,所以如果将字段声明为运行期常量时再删除字节码文件肯定会报错,不信试试?

    确实如此,因为这种运行期的常量是不会被放在常量池当中的,那继续对程序进行改造:

    此时再将MyParent5的字节码文件删掉,照之前的实验应该还是能正常输出的,那结果:

    抛异常了!!那如果将MyParent5中的常量声明为编译期常量结果又会是如何呢?

    依然抛异常,所以这里又可以总结一个东东:只有在真正使用到父类接口的时候(如引用接口中所定义的常量时),才会初始化。

    接下来继续改造:

    然后再将MyParent5删掉:

    因为MyChild5中使用的是常量池的数据,那如果将接口此时改成类呢,在改之前先将final关键字去掉:

    而由于接口中的字段不声明final其实也是常量,所以将字节码MyParent5删掉肯定也是能正常运行的,那接着将其改为class,其它都不变:

    此时再将MyParent5的字节码文件删掉:

    此时就抛异常了,因为对于类来说如果木有声明为final类型就不认为是常量,很显示在初始化子类时肯定也要初始化父类,那当然就抛异常啦,做这些实验就是为了说明之前总结的:当一个接口在初始化时,并不要求其父接口都完成了初始化,只有在真正使用到父类接口的时候(如引用接口中所定义的常量时),才会初始化。

    类加载器准备阶段和初始化阶段的重要意义分析:

    下面再来编写一个新的例子,如下:

    那其结果是多少呢?比较容易理解,如下:

    好!!接下来稍改造一下代码:

    那此时的结果又是多少呢?运行:

    呃~~这是为何,下面打一些日志进一步观测,就会有新大陆发现:

    编译运行:

    实际上在私有构中是counter2是1,只是由于将counter2的静态声明放在它之后了又被置为0了而已,那为什么会这样呢?这里还得从类的加载顺序来分析,具体如下:

    由于咱们在main方法中主动调用了类中的静态方法,如下:

    而根据主动使用的七种方式,它属于这种:

    所以会导致Singleton类的初始化,而在初始化之前还会有一个准备阶段,如:

    那准备阶段干了啥事呢【对于这个阶段接触的少,但是很重要!】?由上往下准备,所以也按上往下的顺序分析,具体如下:

    好,整个类的准备阶段完成,接着准备类的初始化了,而在初始化阶段的时候会给类中的静态变量赋初值,也是按从上往下的顺序执行的,所以:

    好,关键的地方来了:

    那通过上面从准备到初始化阶段的分析,那准备阶段的意义何在呢?看:

    好~~理解了上面代码的整个过程,接着再来修改一下程序,结果又会是怎样,如下:

    理解清楚了之前的那个例子,我想对于这次的修改结果很容易就可以推出来了,这里直接上结果:

    【说明】:上面这个程序没有什么实用价值,但是对于理解类的加载过程是极其有帮助的。

  • 相关阅读:
    uvm_reg_map——寄存器模型(八)
    uvm_reg_block——寄存器模型(七)
    mysql_secure_installation 安全安装(用于生产环境设置)
    一键安装nginx-1.12.2
    nginx优化之隐藏版本号
    shell script 之六:循环 while
    shell script 之五:循环控制 for
    shell script 之四:流程控制 if 分支语句
    shell script 之三:打印输出 echo printf
    shell script 之一:变量和赋值
  • 原文地址:https://www.cnblogs.com/webor2006/p/8904018.html
Copyright © 2011-2022 走看看