`
得小白者天下得
  • 浏览: 7886 次
  • 性别: Icon_minigender_1
  • 来自: 北京
文章分类
社区版块
存档分类
最新评论

java类加载中不会触发初始化的被动引用

    博客分类:
  • java
阅读更多
我们知道,在初始化一个类时,如果它的父类没有进行初始化,那么JVM就会触发其父类的初始化动作。但是,当我们引用类的时候,可不一定会触发其初始化,这种引用类的方式称为被动引用
看下面的例子:
public class NotInit {
	public static void main(String[] args) {
		System.out.println(Child.val);
//		System.out.println(Father.str);
		Father[] father = new Father[4];
		System.out.println(Constant.HELLO);
	}

}


class Father {
	static {
		System.out.println("Father init!");
	}
	
	public static int val = 100;
//	public static String str = "string";
}

class Child extends Father {
	static {
		System.out.println("Child init!");
	}
}

class Constant {
	static {
		System.out.println("Constant init");
	}
	
	public static final String HELLO = "HELLO";
}

见证奇迹的时刻到了!!!程序输出为:
Father init!
100
HELLO


这不科学啊!!!代码中调用了
System.out.println(Child.val);

可是没有竟然没有对Child类进行初始化。这是因为val为静态字段,只有直接定义这个字段的类才会被初始化,故通过子类来引用父类静态字段val,只会触发Father类的初始化,而不会触发Child类的初始化,so 就没有Child类的事。
再来,代码中虽然有
Father[] father = new Father[4];

可是Father类居然没有初始化,这也是情理之中的。这句代码仅仅定义了一个Father类型的一维数组,数组里面什么都没有放!就好比我买了一个可以容纳100L的容器,而且是只能用来装浓硫酸的容器,但是我现在还没把浓硫酸放入容器,所以容器中什么也没有,即是没有初始化。
看官接着往下瞧:
System.out.println(Constant.HELLO);

Constant类没有直接父类,可为何还是没能初始化Constant类。大家也看见了,HELLO是一个常量。常量和一般的变量不一样,因为HELLO是常量,所以Constant类在编译阶段通过常量优化传播,把HELLO所代表的"hello"存储到了NotInit类的常量池中。说人话就是,以后NotInit类对常量Constant.HELLO的引用实际都转化为NotInit类对自身常量池的引用了。在编译结束后,Constant类和NotInit类就劳燕分飞各自走了。

总结是个好习惯!本文描述了类加载过程中的三种被动引用,这些情况下都不会触发相应类的初始化:
一、 通过子类引用父类的静态字段,不会导致子类初始化
二、 通过数组定义来引用类,不会触发该类的初始化
三、 常量在编译阶段会存入调用类的常量池中,本质上并没有直接引用到定义常量的那个类,所以也不会触发定义常量的类的初始化
分享到:
评论

相关推荐

    java相关的2024面试题集锦

    - 虚拟机把描述类的数据从Class文件加载到内存,并对数据进行校验、解析和初始化,最终形成可以被虚拟机直接使用的Java类型,这就是虚拟机的类加载机制 - 类加载机制采用懒加载的方式 - 遇到new、getstatic、...

    VB 加载窗体时触发的Load事件

    VB 加载窗体时触发的Load事件 VB 加载窗体时触发的Load事件

    JAVA_API1.6文档(中文)

    java.lang.ref 提供了引用对象类,支持在某种程度上与垃圾回收器之间的交互。 java.lang.reflect 提供类和接口,以获得关于类和对象的反射信息。 java.math 提供用于执行任意精度整数算法 (BigInteger) 和任意精度...

    Java中File类对文件的几个常见操作实例总结

    Java中File类对文件的几个常见操作实例总结

    类加载器和双亲委派模型加载类、类的加载优先级的详解.docx

    其中 验证 、 准备 、 解析 统称为 连接,类的加载主要是前五个阶段,每个阶段基本上保持如上顺序 开始(仅仅是开始,实际上执行是交叉混合的),只有 解析 阶段不一定,在 初始化后 也有可能才开始执行...

    JavaAPI1.6中文chm文档 part1

    java.lang.ref 提供了引用对象类,支持在某种程度上与垃圾回收器之间的交互。 java.lang.reflect 提供类和接口,以获得关于类和对象的反射信息。 java.math 提供用于执行任意精度整数算法 (BigInteger) 和任意精度...

    java定时触发任务

    java定时任务,参考学习。

    Java80端口占用异常解决方法

    Java80端口占用异常解决方法,在 cmd中查找正在占用80端口的服务,再在进程中取消其服务

    Java 1.6 API 中文 New

    java.lang.ref 提供了引用对象类,支持在某种程度上与垃圾回收器之间的交互。 java.lang.reflect 提供类和接口,以获得关于类和对象的反射信息。 java.math 提供用于执行任意精度整数算法 (BigInteger) 和任意精度...

    java 触发事件应用实例

    触发事件应用实例以及课件Ppt,希望能给你带来帮助!

    jQuery移动web开发中的页面初始化与加载事件

    页面初始化事件...注以下的页面初始化事件在每个“page”只被触发一次,与每次页面在显示或者隐藏的show/hide事件刚刚相反。 pagebeforecreate:页面初始化时,初始化之前触。 pagecreate:页面初始化时,

    浅析jQuery Mobile的初始化事件

    当Jquery Mobile开始执行时,他就会在document对象上触发mobileinit 事件,因为mobileinit事件是在加载后马上触发,所以你需要在Jquery Mobile加载之前绑定你的事件处理函数,所以我建议你如下安排你的js引用顺序 ...

    C#的COM事件在C++和JAVA中触发和响应的实现

    C#的COM事件在C++和JAVA中触发和响应的实现 C#中定义COM的事件,在C++或者JAVA中去实现事件,并由其执行相应的函数后触发COM内部的逻辑,然后响应事件。

    java JComboBox的事件处理

    java JComboBox的事件处理 java JComboBox的事件处理 java JComboBox的事件处理

    自动化控制、事件触发机制研究

    自动化控制、事件触发机制研究,动态事件触发,静态事件触发,自适应事件触发,相对静态事件触发。事件(event)是一个非常重要的概念,我们的程序时刻都在触发和接收着各种事件:鼠标点击事件,键盘事件,以及处理...

    【STM32】HAL库-使用一个定时器使能另一个定时器-主定时器触发模式demo

    如果先初始化从模式定时器3,定时器3工作在触发模式下,TRGI信号来源为定时器2的TRGO,而定时器2还未初始化,故TRGO信号来源默认是UG位,故在定时器2初始化过程中会置位UG位,从而触发定时器3的从模式触发模式,导致...

    java 面试题 总结

    声明方法的存在而不去实现它的类被叫做抽象类(abstract class),它用于要创建一个体现某些基本行为的类,并为该类声明方法,但不能在该类中实现该类的情况。不能创建abstract 类的实例。然而可以创建一个变量,其...

    java流程自动化工具

    三、应用部署:GIT代码拉取,MAVEN打包,SFTP上传,Linux脚本执行,自动化一气呵成,且轻松实现切换用户等交互性需求,数据初始化,多应用的启动顺序或特定条件触发,均可实现自动化操作。 四、模拟操作:接口调试,...

    行业分类-设备装置-被动触发式胎压检测系统及方法.zip

    行业分类-设备装置-被动触发式胎压检测系统及方法.zip

Global site tag (gtag.js) - Google Analytics