类的初始化
程序员文章站
2022-03-09 13:25:19
...
为了使用类需要3步工作:
1.加载。这是由类加载器执行的。该步骤将查找字节码,并从这些字节码创建一个Class对象。
2.链接。在链接阶段将验证类的字节码,为静态域分配存储空间,并且如果必需的话,还将解析这个类创建的对其他类的所有引用。
3.初始化。如果该类具有超类,则对其初始化,执行静态初始化器和静态初始化块。
初始化被延迟到了对静态方法或者非常数静态域进行首次引用时才执行。
看段代码:
import java.util.Random;
class Initable {
static final int staticFinal = 47;
static final int staticFinal2 = ClassInitialization.rand.nextInt(1000);
static {
System.out.println("Initializing Initable");
}
}
class Initable2 {
static int staticNonFinal = 147;
static {
System.out.println("Initializing Initable2");
}
}
class Initable3 {
static int staticNonFinal = 74;
static {
System.out.println("Initializing Initable3");
}
}
public class ClassInitialization {
public static Random rand = new Random(47);
@SuppressWarnings("unchecked")
public static void main(String[] args) throws Exception {
Class initable = Initable.class; //使用.class获得Class对象的引用,不会进行初始化
System.out.println("After creating Initable ref"); //打印输出
//staticFinal为编译期常量。不需对Initable类进行初始化就可以读取
System.out.println(Initable.staticFinal);
//staticFinal2不是编译期常量,要获得它需先进行类初始化,因此会先执行static块中的语句,再打印出staticFinal2
System.out.println(Initable.staticFinal2);
//staticNonFinal不是final的,因此在对它访问时,总是要求在它被读取之前,要先进行链接和初始化。所以也会先执行static块中的语句,再打印出staticNonFinal
System.out.println(Initable2.staticNonFinal);
//使用forName方法获得Class引用会进行初始化,因此会先执行static块中的语句
Class initable3 = Class.forName("Initable3");
System.out.println("After creating Initable3");
//直接打印出staticNonFinal
System.out.println(Initable3.staticNonFinal);
}
}
这段代码的执行结果为:
After creating Initable ref
47
Initializing Initable
258
Initializing Initable2
147
Initializing Initable3
After creating Initable3
74
为什么是这样呢?分析见代码注释
上一篇: react native的优缺点是什么?