为什么在main之前初始化超类中的静态块/静态变量?

时间:2015-07-12 06:54:05

标签: java static-initialization

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方法并仅初始化主类。所以它应该给出输出In test10

有人可以解释为什么我会得到不同的输出吗?

5 个答案:

答案 0 :(得分:1)

当类加载器加载类时,将调用

static初始化程序块。简而言之,这里的执行顺序如下:

  1. 尝试加载test,请参阅此内容取决于sub
  2. 尝试加载sub,请参阅此内容取决于sup
  3. 尝试加载sup
  4. sup已加载,其static块会打印"In Sup"
  5. sub正在恢复加载,其static块打印"In Sub"
  6. test正在恢复加载,a初始化为10
  7. test' static阻止执行并打印" In test10"
  8. test' main函数已执行,并且不执行任何操作,因为它是空的。

答案 1 :(得分:0)

静态块在 main方法之前执行。从test extends subsub extends sup开始,将执行sup的静态块,然后执行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

答案 2 :(得分:0)

无论是否创建类的实例,JVM都会在运行类时加载类。

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

java Test reboot Bob Dot Enzo
     

执行类Test的方法main的初始尝试发现未加载类Test - 也就是说,Java虚拟机当前不包含此类的二进制表示。然后,Java虚拟机使用类加载器来尝试查找这样的二进制表示

答案 3 :(得分:0)

这里我没有创建对象。。它不是关于对象的创建。甚至在创建对象之前,必须加载/初始化类及其相关依赖项。当您访问其中的static methods时,可以加载类(mainstatic)。由于test类取决于subsub取决于sup,因此JVM会按顺序加载它们 - > sub - >测试,以便解决类'test'的依赖关系。除非这样做,否则你的'test'不能使用其超类的字段/方法。

答案 4 :(得分:0)

静态块/变量/方法不可继承,因为它们属于类而不是对象。

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

如果从测试类中删除继承,则只能获得“在test10中”。