当我们说class
被“加载”时,这是什么意思?
例如,据说在类加载时执行Static init
块。何时加载class
?
请参阅Kathy Sierra的书中的代码:
class Bird {
{
System.out.print("b1 ");
}
public Bird() {
System.out.print("b2 ");
}
}
class Raptor extends Bird {
static {
System.out.print("r1 ");
}
public Raptor() {
System.out.print("r2 ");
}
{
System.out.print("r3 ");
}
static {
System.out.print("r4 ");
}
}
class Hawk extends Raptor {
public static void main(String[] args) {
System.out.print("pre "); //1
new Hawk();//2
System.out.println("hawk ");
}
}
以上代码的输出为: r1 r4 pre b1 b2 r3 r2 hawk
我无法理解pre在r1之后打印的结果。哪部分代码加载了Raptor类?
其中一个答案是:
“该类在最后一刻被初始化,但在访问其任何成员之前”。
但按照这个逻辑,不应该在r1之前预先打印?由于第2行在执行第1行后访问类Raptor的构造函数。
答案 0 :(得分:4)
不要混淆类加载(特定于实现)和类初始化,这是非常严格规定的。不幸的是,这两个术语通常被用作同样的东西,但通常短语“类加载的时间”是指类初始化的时间。
作为详细的逐案规则的执行摘要,该类在最后一刻被初始化,但在访问其任何成员之前。
清除该部分后,在您的示例代码中,您有一个类Hawk extends Raptor extends Bird
。 Hawk
是包含程序入口点的类,方法main
。这是初始订单:
Hawk
。它的父类Raptor
是否已初始化?号Raptor
。它的父Bird
是否已初始化?号Bird
。Bird
。Raptor
的静态初始化块。这会打印r1 r4
。Raptor
。Hawk
。Hawk.main()
。这会打印pre
。答案 1 :(得分:0)
通常当您第一次尝试使用该课程时,例如尝试创建一个实例,使用其静态方法之一或存储对类的引用&#39; Class<?>
对象。
请注意,这可能取决于类加载器的实现。
答案 2 :(得分:0)
不同的JVM以不同的方式加载类,但基本规则只是在需要时加载类。如果加载的类需要其他类,则也会加载它们。加载过程是递归的。
下面的代码是类和静态块的简单示例,变量laoding。
pattern="(?i)^(?:testing|dev|)$"
以上程序的输出:
public class Foo {
//instance variable initializer
String s = "abc";
//constructor
public Foo() {
System.out.println("constructor called");
}
//static initializer
static {
System.out.println("static initializer called");
}
//instance initializer
{
System.out.println("instance initializer called");
}
public static void main(String[] args) {
new Foo();
new Foo();
}
}