9

My projects had some developer who loved a non-static initialization block.

What is the alternative to this and what is the downside of this alternative? I would guess: initialize the values in the constructor ?

Why should we use a non-initialization block? As far as I understood the "initialization block" is used to set values when instantiating the class. Is a constructor then not sufficient?

public class BlockTest {
    String test = new String();

    //Non-static initialization block
    {
        test = "testString";
    }
}

This block confuses me and lead to reduced readability. Thanks for your response!

Dimitri Dewaele
  • 10,311
  • 21
  • 80
  • 127

3 Answers3

11

First of all, it doesn't make sense to initialize test to a new String() there, since the initialization block immediately assigns it to something else. Anyways...

One alternative is initializing at the declaration:

public class BlockTest {
    String test = "testString";
}

Another is in the constructor:

public class BlockTest {
    String test;
    public BlockTest () {
        test = "testString";
    }
}

Those are the two main, common options.

There are two main uses for an initialization block. The first is for anonymous classes that have to perform some logic during initialization:

new BaseClass () {
    List<String> strings = new ArrayList<String>();
    {
        strings.add("first");
        strings.add("second");
    }
}

The second is for common initialization that must happen before every constructor:

public class MediocreExample {
    List<String> strings = new ArrayList<String>();
    {
        strings.add("first");
        strings.add("second");
    }
    public MediocreExample () {
        ...
    }
    public MediocreExample (int parameter) {
        ...
    }
}        

However, in both cases there are alternatives that do not use the initialization block:

new BaseClass () {
    List<String> strings = createInitialList();
    private List<String> createInitialList () {
        List<String> a = new ArrayList<String>();
        a.add("first");
        a.add("second");
        return a;
    }
}

And:

public class MediocreExample {
    List<String> strings;
    private void initialize () {
        strings = new List<String>();
        strings.add("first");
        strings.add("second");
    }
    public MediocreExample () {
        initialize();
        ...
    }
    public MediocreExample (int parameter) {
        initialize();
        ...
    }
}        

There are many ways to do these things, use the way that is most appropriate and provides the clearest and most easily maintainable code.

Jason C
  • 38,729
  • 14
  • 126
  • 182
  • +1 for covering the cases where it's an alternative worth consideration. – kiheru Aug 07 '13 at 07:17
  • It is correct that it does not make sense to initialize the string there, but this was just for the example purpose ;-) – Dimitri Dewaele Aug 08 '13 at 06:25
  • Isn't the duplication of the `initialize` method call precisely the problem that the non-static initialization block is trying to solve? Imagine if, by human error, a constructor does not call `initialize`. That can never happen if the code inside `initialize` was placed inside a non-static initialization block. – Alex Mandelias Jul 24 '22 at 05:00
8

Compiler inserts non-static init block into each constructor. The code needed to initialize instance fields is also inserted into each constructor. This

class Test1 {
    int x = 1;
    {
        x = 2;
    }
    Test1() {
        x = 3;
    }
}

compiles into the same bytecoode as this

class Test1 {
    int x;
    Test1() {
        x = 1;
        x = 2;
        x = 3;
    }
}
Evgeniy Dorofeev
  • 133,369
  • 30
  • 199
  • 275
  • 2
    That may be true, but the essence of the question surrounds syntax and observable behavior, not equivalent byte code after compilation. +1 for clearly illustrating the order of initialization though (even if it wasn't necessarily your goal). – Jason C Aug 07 '13 at 07:17
2

initiaization block has no alternative, in fact its an alternative to constructor.

public TestClass {
        TestClass() {

        }
    }

this is useful in case of anonymous class, because you can't have a constructor in that, reason is pretty straight forward, that you don't have name for the class, then you can't have constructor otherwise what will you name it.

new MyClass(){
   //its an anonymous class, you can't use constructor here
      {
      }
  }

however you can initialize the variable inline with your declaration like

public TestClass {
    String test = "value";
}

but it is not an alternative, because you cant perform any operation (say arithmetic or string operations) this way, but you can do in initializer block

public TestClass {
        String test = "value";
        test = test + " not found"//compiler error
        {
         test = test + " not found" // valid
        }
    }
Ankit
  • 6,554
  • 6
  • 49
  • 71
  • You can initialize the fields where they are declared, if you're just assigning values. – Jason C Aug 07 '13 at 07:05
  • 1
    Also note that in all cases there is a way to rewrite without using a non-static initialization block. Not that you'd always want to, it can be a very convenient construct. But it is not quite true that "initialization block has no alternative". – Jason C Aug 07 '13 at 07:15