as in a way to check appropriate use of a static registry:
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 !!!";
}
}
I don't think you should do this. But if you insist, this would get you started:
public static boolean isCalledInStaticInitializer()
{
for (StackTraceElement ste : Thread.currentThread().getStackTrace())
{
if("<clinit>".equals(ste.getMethodName()))
{
return true;
}
}
return false;
}
Source: In section 2.9 of the JVM Specification ("Special Methods"):
"A class or interface has at most one class or interface initialization method and is initialized (§5.5) by invoking that method. The initialization method of a class or interface has the special name <clinit>
"
Thread.currentThread().getStackTrace()
because it seems more elegant and more efficient. I do not think he wants to test ste.getClassName() because he does not know ahead of time which class' static initializers he is guarding against - Mike Clark 2012-04-06 20:45
<clinit>
is well-defined by the JVM specification, and so can be relied upon - Mike Clark 2012-04-07 03:24
Your intention is unnecessary (no one ever does it - I've never seen it etc).
What you want is simply this:
static final IDType id = new IDType(...);
If you need to register the ID somewhere, put that code in the constructor of IDType
if the IDType is immutable, or if it's mutable (unlikely) one option would be to use a factory method in IDType to create-and-register:
public class IDType() {
...
public static IDType createAndRegister(...) {
IDType idType = new IDType(...);
SomeClass.register(idType);
return idType;
}
}
this
accessible to other objects before the constructor is complete is a common cause of concurrency bugs. I don't think this is a good suggestion - erickson 2012-04-05 23:36
Static initialization is done on a per-class basis. So the question the question you might need to ask yourself is "which class's static initialization?". From your use case it looks like the IDRegistry's static initialization is run before any of the classes that register themselves. You might take a different approach and look at something else that you want to enforce about what can be added to the registry.
BTW you detect within a single class's initialization process, by using a final variable that you declare at the very beginning on the class, and then set in a static block at the very end of the class. Since static initialization is done in source order, any code executed as part of the classes static initialization, will see the java default value for the type (i.e. false, 0, null), and any code executed after static initialization will see the final set value.
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;
}
}
But you'll note this doesn't adapt to the cross-class coordination that you want.