Java 程序中时常用些 static {} 这样的结构。 


这样的结构叫 static块 ,一般是一个类初始化时运行的代码。 注意,是类的初始化,不是对象的初始化。 
也就是你在定义对象是,它运行的初始化代码,并且只有第一次定义时才运行。之后就不再运行初始化了。 
一个类中可以可以有很多static块。static块按顺序执行。

看以下代码:

public class TestStatic{
 static{
    System.out.println(1);
 }
 
 static{
    System.out.println(2);
 }
 public static void main(String[] args){
    System.out.println(5);
 }
 static{
    System.out.println(3);
 }
 
 static{
    System.out.println(4);
 }
}





执行的结果是



1



2



3



4



5



一目了然,首先调用的是static静态快的代码,然后调用启动方法.而static块的执行顺序是由代码的编写顺序执行的过程.



static块大家用得比较少,其实就是在对象生成之际产生一系列的static变量。











"java深度历险"一书在讲解“类装载”的一章中,举了以下的例子: 



public interface Assembly{
    public void start();;
}

public class Word implements Assembly{
    static{
        System.out.println("Word static initialization!");;
    }    

    public  void start();{
        System.out.prinlnt("Word starts");;
    }
}

public class Office{
    public static void main(String args[]); throws Exception{
        Office off = new Office();;
        System.out.println("类别准备载入");;
        Class c = Class.forName(args[0],true,off.getClass();.getClassLoader(););;
        System.out.println("类别准备实例化");;
        Object o = c.newInstance();;
        Object o2= c.newInstance();;
   }
}



执行java Office Word,运行结果如下: 

“Loaded Office” 
 “类别准备载入” 
 “Loaded Accembly” 
 “Loaded Word”” 
“Word static initialization” 
 “类别准备实体化”。 

 但是如果将Office.java中Class.forName(args[0],true,off.getClass().getClassLoader())中的true变为false,再执行java Office Word结果显示为: 
 “Loaded Office” 
 “类别准备载入” 
 “Loaded Accembly” 
 “Loaded Word”” 
“类别准备实体化” 
 “Word static initialization”。




显然两次红字部分顺序相反,及static块执行的顺序不同。此书作者提出了原因,原文:

引用



“过去很多java书上提到静态初始化(static initializion block)时,都会说静态初始化区块只是在类第一次载入的时候才会被调用仅仅一次。可是上面输出却发现即使类被载入了,其静态初始化区块也没有被调用,而是在第一次调用newInstance方法时,静态初始化块才被真正调用,应该改成-静态初始化块只是在类被第一次实体化的时候才会被仅仅调用一次。” 




其实,该书作者的上述描述有误。通过一个试验,就可以看出谬误所在。 




public class TestA{
    static{
       System.out.println("Static block executed!");;
    }    
}

public class Test{
    public static void main(String args[]);{
       Test test = new Test();;
       Class.forName("TestA",true,test.getClass();.getClassLoader(););;
   }
}


运行一下,相信大家一定可以看到,“Static block executed!”的输出。这与



引用



而是在第一次调用newInstance方法时,静态初始化块才被真正调用

的说法矛盾。 



其实我想事实是这样的: 


一个类的运行,JVM做会以下几件事情 1、类装载 2、链接 3、初始化 4、实例化;而初始化阶段做的事情是初始化静态变量和执行静态方法等的工作。所以,当Class.forName(args[0],true,off.getClass().getClassLoader());中的true变为false的时候,就是告诉JVM不需再load class之后进行initial的工作。这样,将initial的工作推迟到了newInstance的时候进行。所以,static块的绝对不是什么“只是在类被第一次实体化的时候才会被仅仅调用一次”,而应该是在类被初始化的时候,仅仅调用一次。