类加载过程中的被动引用例子

 
1
package jvm.part_7; 2 /** 3 * 被动使用类字段演示一: 4 * 通过子类引用父类的静态字段,不回导致子类初始化 5 * @author Administrator 6 * 7 * 只会输出 SuperClass init! 8 *分析:对于静态字段,只有直接定义这个字段的类才会被初始化,因此通过其子类来引用父类中定义的静态字段, 9 *只会触发父类的初始化而不会触发子类的初始化; 10 */ 11 class SuperClass{ 12 static{ 13 System.out.println("SuperClass init!"); 14 } 15 public static final int value = 123; 16 } 17 18 class ChildClass extends SuperClass{ 19 static{ 20 System.out.println("ChildClass init!"); 21 } 22 } 23 public class ConstClass { 24 public static void main(String[] args){ 25 System.out.println(ChildClass.value); 26 } 27 }

  上述代码运行之后,只会输出“SuperClass init!”,而不会输出"ChildClass init!",证明子类被又被初始化。

  原因:对于静态字段,只有直接定义这个字段的类才会被初始化,因此通过子类来引用父类中定义的静态字段,只会触发父类的初始化而不会触发子类的初始化。

 1 package jvm.part_7;
 2 
 3 public class NotInitialization {
 4 /**
 5  * 被动引用类字段演示二:
 6  * 通过数组定义来引用类,不回触发此类的初始化。
 7  * @param args
 8  * 
 9  * 没有输出结果,说明数组的定义不会引用类,触发初始化操作
10  */
11     public static void main(String[] args) {
12         SuperClass[] sca = new SuperClass[10];
13     }
14 }

  上述代码运行之后,没有输出,说明数组的定义并不会触发类的初始化操作;

 1 package jvm.part_7;
 2 /**
 3  * 被动引用类字段演示三:
 4  * 常量在编译阶段会存入调用类的常量池中,本质上没有直接引用到定义常量的类,因此不会触发定义常量的类的初始化
 5  * @param args
 6  * 
 7  * 结果仅仅输出 hello world ,而不会初始化ConstClass1 init! 静态代码块;
 8  * 
 9  * 分析:因为虽然在java源码中引用了ConstClass1类中的常量HELLOWORLD,但是在编译阶段将此常量的值存储到了NotInitialization1类的常量池中
10  * 实际上最后引用的是自己的常量池中的常量,并不会引入ConstClass1的加载。
11  */
12 
13 class ConstClass1{
14     static{
15         System.out.println("ConstClass1 init!");
16     }
17     
18     public static final String HELLOWORLD = "hello world";
19 }
20 public class NotInitialization1 {
21 
22     public static void main(String[] args) {
23         System.out.println(ConstClass1.HELLOWORLD);
24     }
25 
26 }
分析:因为虽然在java源码中引用了ConstClass1类中的常量HELLOWORLD,但是在编译阶段将此常量的值存储到了NotInitialization1类的常量池中实际上最后引用的是自己的常量池中的常量,并不会引入ConstClass1的加载。

 

posted @ 2016-03-21 15:06  CfoolishbirdC  阅读(323)  评论(0编辑  收藏  举报