转载:http://student.youkuaiyun.com/space.php?uid=120826&do=blog&id=13762
Thinking in Java告诉我,每当执行Java编译器的时候,编译器会寻找指定的类,当它找到类时,首先需要初始化static变量,因为这些成员可以在没有实例的情况下运行,接着,再按照变量的声明顺序依次初始化类的成员,成员初始化完毕之后才为自己调用构造器,一切进行完毕之后,才可以调用方法。但主类比较特殊,主方法会在构造器之前,static变量初始化之后调用,这是由于Java的惰性初始化,在main方法被调用之前无法知道是否存在主类的实例。
Java的初始化和构造的分离使得Java提供了代码块作为初始化成员的工具和支持无名类的利器,而这样一来,初始化的工作就不免会被扩展,程序员可以嵌入额外的初始化步骤。由于Java的成员分普通成员和static成员,初始化代码块也分static的,例如:
public class Foo{
int a;
int b;
static int c;
{
a=-1;
b=1;
}//这个就是所谓的初始化代码块
static {
c=100;
}//static成员有专属的static初始化代码块
Foo(){Syetem.out.println("Foo creat now!")}
}
public class Foo{
int a;
int b;
static int c;
{
a=-1;
b=1;
}//这个就是所谓的初始化代码块
static {
c=100;
}//static成员有专属的static初始化代码块
Foo(){Syetem.out.println("Foo creat now!")}
}
=======================================================
Class c = Class.forName(args[0],true,off.getClass().getClassLoader());
一个类的运行,JVM做会以下几件事情:
1、类装载
2、链接
3、初始化
4、实例化
而初始化阶段做的事情是初始化静态变量和执行静态方法等的工作。所以,当Class.forName(args[0],true,off.getClass().getClassLoader());中的true变为false的时候,就是告诉JVM不需再load class之后进行initial的工作。这样,将initial的工作推迟到了newInstance的时候进行。所以,static块的绝对不是什么“只是在类被第一次实体化的时候才会被仅仅调用一次”,而应该是在类被初始化的时候,仅仅调用一次。