views:

195

answers:

5

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.

+5  A: 

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.

abhin4v
This is for a very very special use. I would like to have a set of static flags that I can override for testing. Sort of like setting properties. Putting this initialization in a function call opens the door to all kinds of code being run there, but I would rather just limit it to static { DebugUtils.FLAG_TEST_USER = true;}
Artem
All of the code that can be run in the static method can be run in the static block, right? How is it limited?
Lou Franco
I think I was confused... Since the static block usually had variable initialization, I thought it was limited to that. So there are no limitations?
Artem
@Artem: You can do pretty much anything in a static block, the static block(s) of a class are guaranteed to be executed automatically before any code ever accesses that class. Wait now I'm confused if this is what you're asking because of your comment on my answer.
Longpoke
+3  A: 
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?

BigMac66
For one you can do use the overloaded form of Class.forName <http://download.oracle.com/javase/6/docs/api/java/lang/Class.html#forName(java.lang.String, boolean, java.lang.ClassLoader)> . The second argument determines if the class is to be initialized or not. Another possibility is to use Static.class to get a reference to the class, which does not provoke an initialization.
dertoni
Awesome thanks for explaining it to me! I have never used the other form of forName() and was unaware that the single argument form defaults the initialize flag to true.Still my response is valid as it will cause the static initializers to execute which is what I believe Artem was after. The form I suggested loads *AND* explicitly initializes the class.After all these years I still learn new things...
BigMac66
+1  A: 

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.

Aaron Novstrup
A: 

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.

Peter Tillemans
+6  A: 

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.

Longpoke
+1 for quoting the spec!
Aaron Novstrup
Thanks longpoke. Makes a lot of sense. See the comment I made above about using this to override flags. I can certainly do that in a static function, I just thought setting static variables is better done in a static block...
Artem
Nah setting variables doesn't have to be done in a static block, static initializers exist so you can use multiple statements to initialize a static variable, whereas a normal static variable declaration (ie: `static int x = 123; static int y = new Thing().getY();`) can only contain expressions.
Longpoke