在超类类初始化之前,子类终态静态初始化如何进行?

3
我找不到任何具体的SO帖子涉及此特定情况,所以我想问一个我认为是是/否问题。
这里是JLS§12.4.2(Java SE 8),列出6-7:
引用:
  1. [...] 然后, 初始化C的静态常量变量 (§4.12.4、§8.3.2、§9.3.1).
  2. 接下来,如果C是一个类而不是一个接口,并且它的超类尚未被初始化,那么让SC成为它的超类[...]对于列表中的每个S [ SC、SI1、...、SIn ],递归执行整个过程 对于S。必要时首先验证和准备S。[...]
我的问题是:这是否意味着子类的最终静态变量在超类的静态初始化之前初始化(假设最终静态变量作为其声明的一部分初始化)?
1个回答

2
答案是可能的。关键在于常数单词的含义。考虑以下代码。
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 的静态 final 变量在 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

所以,在静态最终Bar.BAR_VALUE被初始化之前,Foo的静态初始化程序已经完成。

值得注意的是:常量变量 是一个使用 常量表达式 初始化的原始类型或 String 类型的 final 变量。 - Roman

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接