我们什么时候说java中加载了类?

时间:2016-09-09 12:58:33

标签: java

当我们说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的构造函数。

3 个答案:

答案 0 :(得分:4)

不要混淆类加载(特定于实现)和类初始化,这是非常严格规定的。不幸的是,这两个术语通常被用作同样的东西,但通常短语“类加载的时间”是指类初始化的时间。

作为详细的逐案规则的执行摘要,该类在最后一刻被初始化,但在访问其任何成员之前。

清除该部分后,在您的示例代码中,您有一个类Hawk extends Raptor extends BirdHawk是包含程序入口点的类,方法main。这是初始订单:

  1. 开始初始化Hawk。它的父类Raptor是否已初始化?号
  2. 开始初始化Raptor。它的父Bird是否已初始化?号
  3. 开始初始化Bird
  4. 完成初始化Bird
  5. 执行Raptor的静态初始化块。这会打印r1 r4
  6. 完成初始化Raptor
  7. 完成初始化Hawk
  8. 开始执行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();
    }
}