子类在超类初始化之前的最终静态初始化?

时间:2016-08-23 21:59:53

标签: java static initialization final

我找不到任何具体的SO帖子提到这个具体案例,所以我想问一下我认为是/否的问题。

这是JLS §12.4.2(Java SE 8),列出6-7:

  
      
  1. [...]然后,   初始化C的静态字段,它们是常量变量   (§4.12.4,§8.3.2,§9.3.1)。
  2.   
  3. 接下来,如果C是一个类而不是一个接口,并且它的超类尚未初始化,那么让SC成为它的超类[...]对于列表中的每个S [SC,SI1,..., SIn],递归执行整个过程   对于S.如有必要,请先验证并准备S. [...]
  4.   

我的问题:是否意味着在超类的静态初始化之前初始化子类的最终静态变量(假设最终的静态初始化为其声明的一部分)?

1 个答案:

答案 0 :(得分:1)

答案是可能是这样的。关键部分是constant字义。

考虑这段代码

class Foo {
    public static final int FOO_VALUE = 1000;

    static {
        System.err.println("FOO Bar.BAR_VALUE=" + Bar.BAR_VALUE);
    }
}

class Bar extends Foo {
    public static final int BAR_VALUE = 2000;

    static {
        System.err.println("BAR Foo.FOO_VALUE=" + Foo.FOO_VALUE);
    }
}

该程序的输出将是

FOO Bar.BAR_VALUE=2000
BAR Foo.FOO_VALUE=1000

在这种情况下,Bar静态最终变量在Foo静态初始化之前初始化。 FOO_VALUEBAR_VALUE都是常量,因此javac可以内联此字段。

但是你可以假装最终变量不是这样的常量来欺骗编译器

class Foo {
    public static final int FOO_VALUE = Integer.valueOf(1000).intValue();

    static {
        System.err.println("FOO " + Bar.BAR_VALUE);
    }
}

class Bar extends Foo {
    public static final int BAR_VALUE =  Integer.valueOf(2000).intValue();

    static {
        System.err.println("BAR " + Foo.FOO_VALUE);
    }
}

输出将是

FOO Bar.BAR_VALUE=0
BAR Foo.FOO_VALUE=1000

因此Foo静态初始值设定项在静态最终Bar.BAR_VALUE初始化之前完成。