2

作为检查静态注册表的适当使用的一种方式:

class AClass {
     static final IDType = IDregistry.registerId(...);
}

class IDRegistry {
     public static registerId(...)
     {
          if(isCalledInStaticInitializer()) {
               return(new IDType(...));
          }
          assert false : "NO NO - can't do this !!!";
     }
}
4

3 回答 3

3

我认为你不应该这样做。但如果你坚持,这会让你开始:

public static boolean isCalledInStaticInitializer()
{
    for (StackTraceElement ste : Thread.currentThread().getStackTrace())
    {
        if("<clinit>".equals(ste.getMethodName()))
        {
            return true;
        }
    }
    return false;
}

资料来源:在JVM 规范(“特殊方法”)的第 2.9 节中:

“一个类或接口最多有一个类或接口初始化方法,并通过调用该方法进行初始化(第 5.5 节)。类或接口的初始化方法具有特殊名称<clinit>

于 2012-04-05T23:50:58.597 回答
1

您的意图是不必要的(从来没有人这样做过-我从未见过等)。

你想要的只是这样:

static final IDType id = new IDType(...);

如果您需要在某处注册 ID,请将代码放在IDTypeIDType 是否不可变或可变(不太可能)的构造函数中,一种选择是使用 IDType 中的工厂方法来创建和注册:

public class IDType() {
    ...
    public static IDType createAndRegister(...) {
        IDType idType = new IDType(...);
        SomeClass.register(idType);
        return idType;
    }
}
于 2012-04-05T23:31:57.390 回答
0

静态初始化是在每个类的基础上完成的。所以你可能需要问自己的问题是“哪个类的静态初始化?”。从您的用例看来,IDRegistry 的静态初始化是在任何注册自己的类之前运行的。您可能会采用不同的方法,并查看您想要强制执行的关于可以添加到注册表的其他内容。

顺便说一句,您在单个类的初始化过程中检测到,通过使用您在类的开头声明的最终变量,然后在类的最后设置一个静态块。由于静态初始化是按源顺序完成的,因此作为类静态初始化的一部分执行的任何代码都将看到该类型的 java 默认值(即 false、0、null),并且在静态初始化之后执行的任何代码都将看到最终集价值。

class AClass {
    static final boolean staticInitDone;

    // Any static initialization done here will see
    // staticInitDone as false, e.g. the
    // Y constructor below would see false.
    static X = new Y();


    static {
        staticInitDone = true;
    }
}

但是你会注意到这并不适应你想要的跨类协调。

于 2012-04-06T03:46:50.353 回答