11

Why would I use a static block:

static {
   B = 10;
}

over:

Integer B = 10;

What is the advantages/disadvantages of one over the other?

1
  • This is less of an answer and more of a warning... static initializers are run in the synthetic clinit() {class init} method, which is implicitly synchronized. Thus, you must be careful with any code you call inside a static initializer, as multithreaded applications could incur deadlock from loading class files! If you need to call out to other classes you don't control or understand, you may want to use a Provider abstraction to delay the initialization until after the class is loaded... Commented Jun 18, 2015 at 3:03

5 Answers 5

14

You should only use a static initializer block, when it is necessary. For example, sometimes you need to do several steps to calculate the final value of the field. In this case you have two opportunities: write a method that calculates the value and declare your field as static final Integer B = calculateB(), or use an initializer block:

static final Integer B;
static {
  int temp = ...;
  ...
  B = temp;
}

In this case I prefer the static block, because a method might be confusing (other developers might try to call it, although it is only meant to be called once during initialization).

The same applies for instance fields as well, although normally one would avoid the unusual initialization block and simply write the initialization logic for fields into the constructor (which is of course not possible for static fields).

Sign up to request clarification or add additional context in comments.

Comments

14

The static block allows you to write more complex initialization logic for the attribute, whereas the one-line initialization limits you to a single expression.

Be aware that initialization blocks exist for both instance and static attributes, for example this one initializes an instance attribute at instantiation time:

private int a;
{ a = 10; }

Whereas this one initializes a static attribute at class loading time:

private static int b;
static { b = 10; }

The initialization procedure is explained in detail in here, as part of the JVM specification.

Comments

4

Static initialization happens when the class is loaded.

E.g. it would be a proper place to initialize member variables that could otherwise need synchronization due to access by multiple threads.

The second case would happen if you called the constructor explicitely.

The usage is different.
E.g. you would prefer the second case for lazy loading of something (if you put it in static initializers it will always load and perhaps you would not want that-prefer to lazy load it)

3 Comments

Sorry im not sure I understand the difference? Surely loading a class is the same as calling its constructor?
No, absolutely not. For example, calling a static method on the class will cause it to be loaded, but will not run any constructors.
@user1176937 also the class is normally loaded only once per java runtime, whereas the constructor will often be called many times.
4

Actually, if you have

private static Integer B = 10;

The compiler will translate to, basically:

private static Integer B;
static {
    B = 10;
}

The thing with static blocks is that you can use the whole language and not just expressions to do initialisation. Imagine you need an array with a bunch of multiples of 7. You could do:

private static Integer[] array;
static {
    array = new Integer[1000];
    for (int i = 0; i < 1000; i++) {
        array[i] = 7 * i;
    }
}

Anyway, you could also do it this way:

private static Integer[] array = initArray();
private static Integer[] initArray() {
    Integer[] result = new Integer[1000];
    for (int i = 0; i < 1000; i++) {
        result[i] = 7 * i;
    }
    return result;
}

Comments

3

First your Integer B appears to be a non static member variable and can not be accessed from a static block. So you either meant to write

//Initialize static field
static {
   B = 10;
}
static Integer B = 10;

or

//Initialize member field
{
   B = 10;
}
Integer B = 10;

In both cases you can use it to initialize B with a value that could cause an exception or do something more complex without writing a special method for init.

{
   try{
      B = thisWillThrowAFileNotFound();
   }catch(FileNotFoundException){
      B = 10;//Set default
   }

}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.