以下Java代码不会调用类B
的静态初始值设定项。为什么呢?
代码:
class A
{
static
{
System.out.println("A static init");
}
public static void f()
{
System.out.println("f() called");
}
}
class B extends A
{
static
{
System.out.println("B static init");
}
}
public class App
{
public static void main( String[] args)
{
B.f(); //invokestatic #16 // Method com/db/test/B.f:()V
}
}
节目输出:
A static init
f() called
在JDK 1.8.0_25上测试
答案 0 :(得分:13)
没有"静态构造函数"。它是一个静态初始化块,只在初始化类时执行。由于您正在调用类A的静态方法(即使您通过类B引用它),因此无需初始化类B.调用B.f();
与调用A.f();
相同。< / p>
如果您创建B类实例或访问B类的静态成员/方法,则将执行B类的静态初始化块。
以下是触发类初始化的仅条件(JLS 12.4.1):
类或接口类型T将在紧接之前初始化 首次出现以下任何一种情况:
T is a class and an instance of T is created. T is a class and a static method declared by T is invoked. A static field declared by T is assigned. A static field declared by T is used and the field is not a constant variable (§4.12.4). T is a top level class (§7.6), and an assert statement (§14.10) lexically nested within T (§8.1.3) is executed.
答案 1 :(得分:5)
由于只有课程A
定义方法f(
),所以课程B
已加载但已初始化。
您可以使用java -verbose:class MyClassName
来检查此内容。
在jdk6 / jdk 8机器上,将打印出来。
[Loaded App from file:/C:/XXXX/]
[Loaded A from file:/C:/XXXXXX]
[Loaded B from file://C:/XXXXXXX]
A static init
f() called
类B
将被初始化 lazily 但是贪婪(因为它被引用)。
将您的代码更改为A.f()
。然后您将看到未加载B
。
[Loaded App from file:/C:/XXXX/]
[Loaded A from file:/C:/XXXXX]
A static init
f() called
注意:类加载和初始化是两回事。有关详细信息,请查看Class.forName()
的文档。