问题
What is the best and cleanest way to do this? Specifically, I need some code in a static initializer block to run in that class, but I'd like to make this as clean-looking as possible.
回答1:
Loading != Initialization.
You want your class to be initialized (this is when static blocks executed, among other things).
An excerpt from the Java Language Specification says:
A class or interface type T will be initialized immediately before the first occurrence of >any one of the following:
- T is a class and an instance of T is created.
- T is a class and a static method declared by T is invoked.
- A static field declared by T is assigned.
- A static field declared by T is used and the field is not a constant variable (§4.12.4).
- T is a top-level class, and an assert statement (§14.10) lexically nested within T is executed.
Invocation of certain reflective methods in class Class and in package java.lang.reflect also causes class or interface initialization. A class or interface will not be initialized under any other circumstance.
Doh, anovstrup, already said it: Just make an empty static function called init
. Be sure to document that well... I personally can't see any use case for this in the context of well formed code though.
回答2:
You can use the following code to force initialization of a class:
//... Foo.class ... //OLD CODE
... forceInit(Foo.class) ... //NEW CODE
/**
* Forces the initialization of the class pertaining to
* the specified <tt>Class</tt> object.
* This method does nothing if the class is already
* initialized prior to invocation.
*
* @param klass the class for which to force initialization
* @return <tt>klass</tt>
*/
public static <T> Class<T> forceInit(Class<T> klass) {
try {
Class.forName(klass.getName(), true, klass.getClassLoader());
} catch (ClassNotFoundException e) {
throw new AssertionError(e); // Can't happen
}
return klass;
}
回答3:
try
{
Class.forName(class name as string)
}
catch(ClassNotFoundException e)
{
whatever
}
That should do it.
@Longpoke
Maybe I am misunderstanding something then. Can you create an example where a class is loaded but the static initializer is not executed? Here is an example that does nothing but print out that it has loaded:
package test;
public class TestStatic
{
public static void main(String[] args)
{
try
{
Class.forName("test.Static");
}
catch (ClassNotFoundException e)
{
e.printStackTrace();
}
}
}
With the following Static class being loaded:
package test;
public class Static
{
static
{
System.out.println("Static Initializer ran...");
}
}
If the static initializers are not ran until the conditions you listed are met then why does this println get executed when I run my test? That is which of your listed conditions am I meeting?
回答4:
Invisible dependencies between classes is not a good idea. I suggest moving the code in static initializer block to a static method and calling it directly in the dependent class. The static initializer block can be rewritten to call the newly created static method.
回答5:
One solution would be to call a static method:
public class A {
static { DebugUtils.FLAG_TEST_USER = true; }
static void init() {}
}
Then invoke A.init()
to force initialization.
However, doing this at all is a code smell. Consider replacing your static code with a standard constructor in a singleton object.
回答6:
If you need to statically initilize something in a Class that means there must be client classes dependent on that.
If there is one client, or let's call it a natural home for the initializing block, I think it would be cleanest to initialize it there.
For the many equal clients case, it may be a good idea to verify from these classes that the static initalization in the other class was successful. Then the coupling is documented and you are sure the class is always initialized before the first client needs it.
来源:https://stackoverflow.com/questions/3560103/how-to-force-a-class-to-be-initialised