加载器二:类初始化的时机

上节讲了Java类初始化的步骤,那么什么时候执行初始化操作呢?

下面6种方式使用某个类或接口时,系统会初始化类或接口:

创建类的实例。为某个类创建实例的方法包括:使用new来创建实例;通过反射创建实例;通过反序列化的方式创建

调用某个类的类方法(静态方法)

访问某个类或接口的类变量,或为该类变量赋值

使用反射方式来强制创建某个类或接口对应的java.lang.Class对象。例如:Class.forName(xxx.xxx.Person);如果系统还未初始化Person类,则这行代码将会刀子该Person类初始化,返回Person类对应的java.lang.Class对象。

初始化某个类的子类。当初始化某个类是,系统会检查这个类是否有父类及该父类是否初始化,最终的结果是子类上级的所有父类都会被初始化。

直接使用java.exe命令 来运行某个主类。当这个主类运行时,会先初始化该主类。例如在一个类中运行main函数。

除此之外,还有以下情形需要特别指出。
对于 一个final修饰的类变量,如果该类变量的值在编译时就可以确定下来,那么这个类变量相当于“宏变量”,也可理解成“常量”。Java便一起去会在编译时直接把这个类变量出现的地方替换成它的值,因此即使程序使用该静态变量也不会导致该类的初始化。

class MyTest {
    static {
        System.out.println("使用final的静态变量----静态初始化块...");
    }

    // 使用一个字符串直接量为static final的类变量赋值
    static final String compileConstant = "final静态变量";
}
class MyTest2 {
    static {
        System.out.println("没有使用final的静态变量----静态初始化块...");
    }

    // 使用一个字符串直接量为static final的类变量赋值
    static String compileConstant = "静态变量";
}
public class CompileConstantTest {
    public static void main(String[] args) {
        // 访问、输出MyTest中的compileConstant类变量
        System.out.println(MyTest.compileConstant); //
        System.out.println(MyTest2.compileConstant); //
    }
}
/*
结果:
final静态变量
没有使用final的静态变量----静态初始化块...
静态变量

*/
代码

 

上面的程序中有一个String类型的变量,但该变量使用了final修饰,并且使用static修饰为静态变量,所以可以在编译时确定,这是该变量被当成“宏变量”处理。

当某个静态变量(类变量)使用final修饰,但是它的值没有办法确定,那么通过该类访问这个变量就会导致该类初始化,例如

static String compileConstant2 = System.currentTimeMillis()+"";

这样会使该类初始化。

posted @ 2015-08-05 13:50  傅长路  阅读(314)  评论(0编辑  收藏  举报