我需要在静态初始化之前做一些事情。
我想出了下面的代码。
这是一个理智的方式吗?
感谢
class Needs {
static final int tobeStaticInitialized;
static {
while(!SomethingRequired.isDone())
try {
Thread.sleep(0);
} catch(InterruptedException e) {
e.printStackTrace();
}
tobeStaticInitialized=42;
}
}
class SomethingRequired {
static boolean isDone() {
return done;
}
static void done() {
System.out.println("doing something required before access.");
done=true;
}
private static boolean done;
}
public class Initialize implements Runnable {
public static void main(String[] arguments) throws InterruptedException {
new Thread(new Initialize()).start();
Thread.sleep(50);
SomethingRequired.done();
}
@Override public void run() {
System.out.println("trying to access someting.");
int x=Needs.tobeStaticInitialized;
System.out.println("got it: "+x);
}
}
答案 0 :(得分:1)
我认为,当它仍然处于“默认初始化”状态时,你想要获得tobeStaticInitialized
的值;即在静态初始化程序块运行之前。
它会起作用吗?
我认为答案是否定的。
JLS说这个(12.4.1):
类或接口类型T将在紧接之前初始化 首次出现以下任何一种情况:
T是一个类,并创建了一个T实例。
调用T声明的静态方法。
分配由T声明的静态字段。
使用T声明的静态字段,该字段不是常量变量(§4.12.4)。
...
在您的示例中,此语句应触发类初始化:
int x = Needs.tobeStaticInitialized;
因此分配给x
的值应为42
。
有一个更大的问题,即如何实现您的目标。如果这是一个“绿色领域”问题,那么你可以尝试利用规范中的这个“漏洞”:
初始化代码不受限制的事实允许构建示例,其中在评估初始化表达式之前,当它仍然具有其初始默认值时,可以观察到类变量的值,但是这样的示例在实践中很少见。 / p>
规范提到涉及具有循环依赖关系的类的示例。
问题在于,如果你有一个现有的类,你可能无法在不修改类本身的情况下制造圆形。但是如果你可以修改类,最好重写它的静态初始化逻辑。
如果你真的陷入困境并且你无法在源代码级别更改初始化,那么你应该考虑使用“字节码工程”黑客。这是“理智”吗? IMO,不!