首先Sub.B中对静态数据进行了引用,Sub类要进行初始化了。同时,其父类Parent要先进行初始化动作。Parent初始化后,A=2,所以B=2;上个过程相当于:

    static class Parent{ 
        <clinit>(){ 
            public static int A=1; 
            static{ 
                A=2; 
            } 
        } 
    } 
    static class Sub extends Parent{ 
        <clinit>(){  //jvm会先让父类的该方法执行完在执行这里 
        public static int B=A; 
        } 
    } 
    public static void main(String[] args){ 
        System.out.println(Sub.B); 
    }

  <clinit>();方法对类跟接口来说不是必须的,加入类或者接口中没有对类变量进行赋值且没有静态代码块,<clinit>()方法不会被编译器生成。

  由于接口里面不能存在static{}这种静态代码块,但仍然可能存在变量初始化时的变量赋值操作,所以接口里面也会生成<clinit>()构造器。但跟类的不同的是,执行子接口的<clinit>();方法前并不需要执行父接口的<clinit>();方法,当父接口中定义的变量被使用时,父接口才会被初始化。

  另外,接口的实现类在初始化的时候也一样不会执行接口的<clinit>();方法。

  另外,jvm会保证一个类的<clinit>();方法在多线程环境下能被正确地加锁同步。<因为初始化只会被执行一次>。

  下面用个例子说明一下:

    public class DeadLoopClass { 
    
        static{ 
            if(true){ 
            System.out.println("要被 ["+Thread.currentThread()+"] 初始化了,下面来一个无限循环"); 
            while(treu){}    
            } 
        } 
         
        /** 
         * @param args 
         */
        public static void main(String[] args) { 
            // TODO Auto-generated method stub 
            System.out.println("toplaile"); 
            Runnable run=new Runnable(){ 
    
                @Override
                public void run() { 
                    // TODO Auto-generated method stub 
                    System.out.println("["+Thread.currentThread()+"] 要去实例化那个类了"); 
                    DeadLoopClass d=new DeadLoopClass(); 
                    System.out.println("["+Thread.currentThread()+"] 完成了那个类的初始化工作"); 
                     
                }}; 
                 
                new Thread(run).start(); 
                new Thread(run).start(); 
        } 
    
    }

  这里面,运行的时候将会看到阻塞现象。