静态初始化之前如何做某事

时间:2015-10-05 00:56:31

标签: java initialization static-methods

我需要在静态初始化之前做一些事情。

我想出了下面的代码。

这是一个理智的方式吗?

感谢

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);
    }
}

1 个答案:

答案 0 :(得分:1)

我认为,当它仍然处于“默认初始化”状态时,你想要获得tobeStaticInitialized的值;即在静态初始化程序块运行之前。

它会起作用吗?

我认为答案是否定的。

JLS说这个(12.4.1):

  

类或接口类型T将在紧接之前初始化   首次出现以下任何一种情况:

     
      
  • T是一个类,并创建了一个T实例。

  •   
  • 调用T声明的静态方法。

  •   
  • 分配由T声明的静态字段。

  •   
  • 使用T声明的静态字段,该字段不是常量变量(§4.12.4)。

  •   
  • ...

  •   

在您的示例中,此语句应触发类初始化:

   int x = Needs.tobeStaticInitialized;

因此分配给x的值应为42

有一个更大的问题,即如何实现您的目标。如果这是一个“绿色领域”问题,那么你可以尝试利用规范中的这个“漏洞”:

  

初始化代码不受限制的事实允许构建示例,其中在评估初始化表达式之前,当它仍然具有其初始默认值时,可以观察到类变量的值,但是这样的示例在实践中很少见。 / p>

规范提到涉及具有循环依赖关系的类的示例。

问题在于,如果你有一个现有的类,你可能无法在不修改类本身的情况下制造圆形。但是如果你可以修改类,最好重写它的静态初始化逻辑。

如果你真的陷入困境并且你无法在源代码级别更改初始化,那么你应该考虑使用“字节码工程”黑客。这是“理智”吗? IMO,不!