java类加载中不会触发初始化的被动引用_JAVA_编程开发_程序员俱乐部

中国优秀的程序员网站程序员频道CXYCLUB技术地图
热搜:
更多>>
 
您所在的位置: 程序员俱乐部 > 编程开发 > JAVA > java类加载中不会触发初始化的被动引用

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

 2014/9/2 21:33:47  得小白者天下得  程序员俱乐部  我要评论(0)
  • 摘要:我们知道,在初始化一个类时,如果它的父类没有进行初始化,那么JVM就会触发其父类的初始化动作。但是,当我们引用类的时候,可不一定会触发其初始化,这种引用类的方式称为被动引用。看下面的例子:publicclassNotInit{publicstaticvoidmain(String[]args){System.out.println(Child.val);//System.out.println(Father.str);Father[]father=newFather[4];System.out
  • 标签:Java
我们知道,在初始化一个类时,如果它的父类没有进行初始化,那么JVM就会触发其父类的初始化动作。但是,当我们引用类的时候,可不一定会触发其初始化,这种引用类的方式称为被动引用
看下面的例子
class="java" name="code">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类就劳燕分飞各自走了。

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