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虚拟机一书。

 

posted @ 2014-11-12 17:05  廖凯林  阅读(1322)  评论(0编辑  收藏  举报