What is the alternative to a non-static initialization block?
Asked Answered
C

3

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!

Craw answered 7/8, 2013 at 7:1 Comment(0)
P
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.

Pilpul answered 7/8, 2013 at 7:4 Comment(3)
+1 for covering the cases where it's an alternative worth consideration.Cosmogony
It is correct that it does not make sense to initialize the string there, but this was just for the example purpose ;-)Craw
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.Winch
S
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;
    }
}
Sidnee answered 7/8, 2013 at 7:10 Comment(1)
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).Pilpul
E
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
        }
    }
Entire answered 7/8, 2013 at 7:4 Comment(2)
You can initialize the fields where they are declared, if you're just assigning values.Pilpul
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".Pilpul

© 2022 - 2024 — McMap. All rights reserved.