我编写了以下代码并为超类创建了对象。
class SuperClass{
static int a=2;
static int b(){
return 2;
}
int c(){
return 2;
}
SuperClass(){
System.out.println("Super");
}
static {
System.out.println("super");
}
}
public class Sub extends SuperClass{
Sub(){
System.out.println("Sub");
}
static {
System.out.println("sub");
}
static int b(){
return 3;
}
int c(){
return 3;
}
public static void main(String ax[]){
SuperClass f =new SuperClass();
System.out.println(f.c());
System.out.print(SuperClass.b());
}
}
当我检查输出时,它如下:
super
sub
Super
2
2
我知道只有在初始化类的对象或进行任何静态引用时才执行静态块。但在这里,我没有将这些中的任何一个发给Sub类。那为什么我看到“sub”即子类'静态块输出?
答案 0 :(得分:37)
我知道只有在初始化类的对象或进行任何静态引用时才执行静态块。但是在这里,我没有将这些中的任何一个发给Sub类。
您的代码没有,但为了运行main
,必须加载Sub
。所以运行它的静态初始化器。
例如,我假设你这样运行:
java Sub
java
工具必须加载Sub
才能调用Sub.main
。这是静态引用(访问,真的)导致静态初始化程序运行。 (如果在IDE中运行它,IDE将执行java
工具部分,但结果是相同的。)
所以这就是发生的事情:
java
触发加载Sub
JVM必须加载SuperClass
才能加载Sub
因此,我们看到他们的静态初始化程序按顺序运行(SuperClass
,然后是Sub
):
super
sub
java
工具调用main
main
来电new SuperClass
中的代码:
Super
main
来电f.c()
2
main
来电SuperClass.b
中的代码:
2
Holger帮助points out,§5.5 - Initialization中的JVM规范和相关§5.2 - Java Virtual Machine Startup:
类或接口的初始化包括执行其类或接口初始化方法(第2.9节)。
类或接口C只能由于以下原因而初始化:
...
如果C是一个类,则初始化其子类之一。
如果C是一个类,则将其指定为Java Virtual Machine启动时的初始类(第5.2节)。
倒数第二个要点涵盖SuperClass
,最后一个要点涵盖Sub
。
答案 1 :(得分:12)
由于您的main()
方法是Sub
的成员,因此需要加载该类才能让您的程序运行。
答案 2 :(得分:9)
在调用main
时,将调用所有静态初始化程序,首先是超类,然后是子类。
这解释了你观察到的输出。
答案 3 :(得分:3)
在加载类时运行静态块。通常是因为你调用构造函数或静态成员。在这种情况下,这是因为您执行了main方法(静态成员)。
旁注: