不为派生类调用静态初始值设定项

时间:2015-01-13 13:12:22

标签: java

以下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上测试

2 个答案:

答案 0 :(得分:13)

没有&#34;静态构造函数&#34;。它是一个静态初始化块,只在初始化类时执行。由于您正在调用类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()的文档。