我有以下代码,错误已注释
public final class MyStaticClass {
private MyStaticClass() {}
static {
a = new A();
b = new B(a); // Cannot access a field before it is defined
}
private static final A a;
private static final B b;
}
我对使用静态初始值设定项还很陌生,但我不知道为什么不能编译。我浏览了一些关于这个主题的帖子,并且看到了初始化运行的顺序,但这似乎并不违反规则。当 b 被初始化时,a 应该已经被初始化了。
我有一个变通办法,就是将此类设置为单例,但这样做会降低代码的可读性。我很想知道这里出了什么问题。
最佳答案
这在 JLS 8.3.3 中有解释.事实上,有几种方法可以修复它。
使用限定名称a
:
// #1
public final class MyStaticClass {
static {
a = new A();
b = new B(MyStaticClass.a);
}
private static final A a;
private static final B b;
}
如果 a
和 b
是在实例初始化程序中初始化的实例字段,则 a
可以限定为 this.a
.
将对 a
的前向引用放在赋值的左侧:
// #2
public final class MyStaticClass {
static {
b = new B(a = new A());
}
private static final A a;
private static final B b;
}
当然,将声明以文本形式放在引用之前:
// #3
public final class MyStaticClass {
private static final A a;
private static final B b;
static {
a = new A();
b = new B(a);
}
}
根据 JLS,#3 在技术上不是必需的(“这些类变量在范围内”),而是旨在捕获一种特殊类型的错误,其中字段初始化顺序不正确:
public final class MyStaticClass {
private static final B b = new B(a); // a is null
private static final A a = new A();
}
(尽管我只是向您展示了两种方法来阻止它并无论如何都会犯错误。)
我推荐 #1 或 #3,因为 #2 有点深奥。您似乎没有犯此规则旨在捕获的错误。
关于java - 静态初始值设定项不能在定义之前引用字段,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26784924/