views:

422

answers:

7

As far as I understood the "static initialization block" is used to set values of static field if it cannot be done in one line. But I do not understand why we need a special block for that. For example we declare a field as static (without a value assignment). And then write several lines of the code which generate and assign a value to the above declared static field. Why do we need this lines in a special block like: static {...}?

A: 

And where to call those lines if not in such a static block ?

thelost
And when we call these lines if they are in the static block?
Roman
You don't call them directly. The JVM runs them when the class is being initialized when it is first loaded.
Pointy
@Pointy, but why the same cannot be done without the static block? We just run all lines in the class when the class is being initialized when it is first loaded.
Roman
Where would you put those lines of code? Why don't you like these blocks?
Pointy
+1  A: 

You can execute bits of code once for a class before an object is constructed in the static blocks.

E.g.

class A {
  static int var1 = 6;
  static int var2 = 9;
  static int var3;
  static long var4;

  static Date date1;
  static Date date2;

  static {
    date1 = new Date();

    for(int cnt = 0; cnt < var2; cnt++){
      var3 += var1;
    }

    System.out.println("End first static init: " + new Date());
  }
}
Pierre-Antoine LaFayette
+7  A: 

Here's an example:

  private static final HashMap<String, String> MAP = new HashMap<String, String>();
  static {
    MAP.put("banana", "honey");
    MAP.put("peanut butter", "jelly");
    MAP.put("rice", "beans");
  }

The code in the "static" section(s) will be executed at class load time, before any instances of the class are constructed (and before any static methods are called from elsewhere). That way you can make sure that the class resources are all ready to use.

It's also possible to have non-static initializer blocks. Those act like extensions to the set of constructor methods defined for the class. They look just like static initializer blocks, except the keyword "static" is left off.

Pointy
For that particular example sometimes the *double brace* pattern is been "abused" :)
BalusC
It can be abused, but on the other hand it does clean up some messes, and makes some kinds of code a little more "solid." I program in Erlang for fun, and you get hooked on not needing local variables :-)
Pointy
<< The code in the "static" section(s) will be executed at class load time, before any instances of the class are constructed (and before any static methods are called from elsewhere). That way you can make sure that the class resources are all ready to use. >> (Which "Pointy" mentioned in above answer) this is very important point to be noted when it comes to static block execution.
learner
+9  A: 

If they weren't in a static initialization block, where would they be? How would you declare a variable which was only meant to be local for the purposes of initialization, and distinguish it from a field? For example, how would you want to write:

public class Foo
{
    private static final int widgets;

    static
    {
        int first = Widgets.getFirstCount();
        int second = Widgets.getSecondCount();
        // Imagine more complex logic here which really used first/second
        widgets = first + second;
    }
}

If first and second weren't in a block, they'd look like fields. If they were in a block without static in front of it, that would count as an instance initialization block instead of a static initialization block, so it would be executed once per constructed instance rather than once in total.

Jon Skeet
+1  A: 

If your static variables need to be set at runtime then a static {...} block is very helpful.

For example, if you need to set the static member to a value which is stored in a config file or database.

Also useful when you want to add values to a static Map member as you can't add these values in the initial member declaration.

Marcus
+4  A: 

As a sidenote, you can also construct a similar block:

{
    // Do Something...
}

This gets called everytime the class is constructed. The static block only gets called once, no matter how many objects of that type you create.

Example:

public class Test {

    static{
        System.out.println("Static");
    }

    {
        System.out.println("Non-static block");
    }

    public static void main(String[] args) {
        Test t = new Test();
        Test t2 = new Test();
    }
}

This prints:

Static
Non-static block
Non-static block
Frederik Wordenskjold
+1  A: 

It's also useful when you actually don't want to assign the value to anything, such as loading some class only once during runtime.

E.g.

static {
    try {
        Class.forName("com.example.jdbc.Driver");
    } catch (ClassNotFoundException e) {
        throw new ExceptionInInitializerError("Cannot load JDBC driver.", e);
    }
}

Hey, there's another benefit, you can use it to handle exceptions. Imagine that getStuff() here throws an Exception which really belongs in a catch block:

private static Object stuff = getStuff(); // Won't compile: unhandled exception.

then a static initializer is useful here. You can handle the exception there.

Another example is to do stuff afterwards which can't be done during assigning:

private static Properties config = new Properties();

static {
    try { 
        config.load(Thread.currentThread().getClassLoader().getResourceAsStream("config.properties");
    } catch (IOException e) {
        throw new ExceptionInInitializerError("Cannot load properties file.", e);
    }
}

To come back to the JDBC driver example, any decent JDBC driver itself also makes use of the static initializer to register itself in the DriverManager. Also see this and this answer.

BalusC