为什么 super class 中的 static blocks/static 变量在 main 之前初始化?

Why are static blocks/static variables in super class initialized before main?

public class sup {
    static {
        System.out.print("In Sup  ");
    }
}


public class sub extends sup {
    static {
        System.out.print("In Sub");
    }
}

final public class test extends sub {
    static int a = 10;

    static {
        System.out.print("  In test" + a);
    }

    {
        System.out.print("  In test" + a);
    }

    public static void main(String[] args) {

    }
}

输出:

In Sup  In Sub  In test10

但这里我不是在创建对象。 JVM 应该调用静态的 main 方法并仅初始化 main class。所以它应该给出输出 In test10

谁能解释一下为什么我得到不同的输出?

静态块执行beforemain方法。由于test extends subsub extends supsup的静态块将被执行,然后是sub的静态块,最后是test的静态块。

详见JLS - 12.4.1. When Initialization Occurs

class Super {
    static { System.out.print("Super "); }
}
class One {
    static { System.out.print("One "); }
}
class Two extends Super {
    static { System.out.print("Two "); }
}
class Test {
    public static void main(String[] args) {
        One o = null;
        Two t = new Two();
        System.out.println((Object)o == (Object)t);
    }
}

这个例子演示了执行顺序,输出将是

Super Two false

static 初始化程序块在 class 加载程序加载 class 时被调用。简而言之,这里的执行顺序如下:

  1. 尝试加载test,看到它取决于sub
  2. 尝试加载sub,看到它取决于sup
  3. 尝试加载 sup
  4. sup 已加载,其 static 块打印 "In Sup"
  5. sub 的加载已恢复,其 static 块打印 "In Sub"
  6. test的加载恢复,a初始化为10.
  7. teststatic 块被执行并打印 " In test10"
  8. testmain 函数被执行,但什么都不做,因为它是空的。

当 class 为 运行 时,无论您是否创建 class 的实例,JVM 都会加载 class。

这在 Java 语言规范的 Section 12.1.1 中有明确规定。

java Test reboot Bob Dot Enzo

The initial attempt to execute the method main of class Test discovers that the class Test is not loaded - that is, that the Java Virtual Machine does not currently contain a binary representation for this class. The Java Virtual Machine then uses a class loader to attempt to find such a binary representation

这里我不是在创建对象。。这与对象的创建无关。即使在创建对象之前,也必须加载/初始化 class 及其相关依赖项。 类 可以在您访问其中存在的 static methods 时加载(mainstatic)。因为你的 test class 依赖于 subsub 依赖于 sup,JVM 加载它们的顺序是 sup --> sub --> test 所以class 'test' 的依赖关系已解决。除非这样做,否则您的 'test' 不能使用其超 classes 的字段/方法。

static block/variable/methods 不可继承,因为它们属于 class 而不是对象。

你得到这个输出的原因是,JVM 需要加载 main class 的完整层次结构来执行 main 方法(parent class 然后是 child)。

如果您从测试 class 中删除继承,您将只得到 'In test10'。