06-引用类初始化问题

     

1.概念
       在类与类之间引用时,是否要对引用类进行初始化,在jvm规范中规定了以下五种情况需要进行初始化引用类
      ■ 遇到 new 、 getstatic、putstatic或者invokestatic 这四条指令,生成这四条指令常见的操作: 使用new关键字实例化对象、读取或者设置一个类的静态字段(被final修饰的常量已在编译器把结果存入了常量池的静态字段除外)的时候、调用一个类的静态方法;
      ■ 使用反射的对类进行调用的时候,如果没有初始化,需要先初始化引用类;
      ■ 当初始化一个类的时候,如果发现父类还没有进行初始化,那么需要进行父类的初始化操作;
      ■ 当jvm启动的时候,用户需要指定一个要执行的主类,jvm会先初始化该类;
      ■ 使用jdk7动态语言支持,如果一个java.lang.invoke.MethodHandle实例最后解析结果为REF_getstatic,REF_putstatic,REF_invokestatic的方法句柄,并且这个方法句柄所对应的类没有进行初始化,则需要先触发其初始化
      以上行为成为对一个类进行主动引用,除此之外,所有应用类的方式都不会触发类的初始化过程,称为被动调用
2. 案例
       2.1   
对于静态字段,只有直接定义这个字段的类才会被初始化

        

package exception.test;



public class SuperClass {



	static{

		System.out.println("super class init ! ");

	}

	public static int value = 123 ;



	

}



package exception.test;



public class SubClass  extends SuperClass{



		static{

			System.out.println(" sub class init . ");

		}

}







package exception.test;



public class ExcpetionDemo {



	public static void main(String[] args) {

		 

		/*String str1 = new String("abc") ; //执行堆中的对象

		String str2 = "abc" ; //执行栈中的一个常量 abc

		System.out.println(str1 == str2 );

		

		   */

		System.out.println(SubClass.value); //对于静态字段,只有直接定义这个字段的类才会被初始化

	} 

	



}

  

            执行结果: 
super class init ! 

123

  

   2.2 

   执行一下代码
package exception.test;



public class Test {



	public static void main(String[] args) {

		SuperClass[] sca = new SuperClass[10] ;

	}

}

  无任何输出,没有任何对static的调用,不会初始化;

 

   2.3 

package exception.test;



public class ConstantClass {

	static{

		System.out.println(" ConstantClass  init ");

	}

	

	public final static String value = "123" ;



}





package exception.test;



public class CallConstant {



	public static void main(String[] args) {

		System.out.println(ConstantClass.value);

	}

}

  输出结果 只打印123
常量value在类编译的时候就加入了CallConstant类的常量池中, 执行 ConstantClass.value 实际上是CallConstant对自身常量池的调用。
 
  

 

这里涉及到的案例来源于深入理解java虚拟机一书。

 

你可能感兴趣的:(类初始化)