Subclass superclass class 初始化之前的最终静态初始化?
Subclass final static initialization prior to superclass class initialization?
我找不到任何具体的 SO post 提到这个具体案例,所以我想问一下我认为是 yes/no 的问题。
这里是 JLS §12.4.2 (Java SE 8),清单 6-7:
- [...] Then,
initialize the static fields of C which are constant variables
(§4.12.4, §8.3.2, §9.3.1).
- Next, if C is a class rather than an interface, and its superclass has not yet been initialized, then let SC be its superclass [...] For each S in the list [ SC, SI1, ..., SIn ], recursively perform this entire procedure
for S. If necessary, verify and prepare S first. [...]
我的问题:这是否意味着子类的最终静态变量在超类的静态初始化之前被初始化(假设最终静态变量作为其声明的一部分被初始化)?
答案是可能是这样。关键部分是一个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_VALUE
和 BAR_VALUE
都是 常量 所以 javac
可以内联这个字段。
但是你可以通过这种方式假装 final 变量不是常量来欺骗编译器
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
初始化之前完成。
我找不到任何具体的 SO post 提到这个具体案例,所以我想问一下我认为是 yes/no 的问题。
这里是 JLS §12.4.2 (Java SE 8),清单 6-7:
- [...] Then, initialize the static fields of C which are constant variables (§4.12.4, §8.3.2, §9.3.1).
- Next, if C is a class rather than an interface, and its superclass has not yet been initialized, then let SC be its superclass [...] For each S in the list [ SC, SI1, ..., SIn ], recursively perform this entire procedure for S. If necessary, verify and prepare S first. [...]
我的问题:这是否意味着子类的最终静态变量在超类的静态初始化之前被初始化(假设最终静态变量作为其声明的一部分被初始化)?
答案是可能是这样。关键部分是一个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_VALUE
和 BAR_VALUE
都是 常量 所以 javac
可以内联这个字段。
但是你可以通过这种方式假装 final 变量不是常量来欺骗编译器
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
初始化之前完成。