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

  • 相关阅读:
    The 2014 ACM-ICPC Asia Xi'an Regional Contest — F题 Color
    CodeForces 358D — Dima and Hares
    VIJOS国庆节模拟赛之繁星春水
    两个算法
    HDU 4901
    Andrew Stankevich Contests #2
    HDU 4701
    HDU 5033
    程序安装出现错误代码为2869
    常用正则表达式总结(以后加了再补充)
  • 原文地址:https://www.cnblogs.com/liaokailin/p/4092734.html
Copyright © 2020-2023  润新知