Skip to content
Java polymorphism 5 min read

Instance Initializer Block

When an object is created in Java, there’s a small but powerful feature that runs before the constructor body — the instance initializer block. It lets you write shared setup code in one place, no matter how many constructors your class has.

What Is an Instance Initializer Block?

An instance initializer block (IIB) is a block of code written directly inside a class body (not inside any method or constructor) wrapped in curly braces {}. It executes every time a new instance of the class is created, right before the constructor runs.

public class Greeter {

    String message;

    // Instance initializer block
    {
        message = "Hello from the initializer!";
        System.out.println("Instance initializer ran");
    }

    Greeter() {
        System.out.println("Default constructor ran");
    }

    Greeter(String extra) {
        System.out.println("Parameterized constructor ran: " + extra);
    }

    public static void main(String[] args) {
        Greeter g1 = new Greeter();
        Greeter g2 = new Greeter("World");
    }
}

Output:

Instance initializer ran
Default constructor ran
Instance initializer ran
Parameterized constructor ran: World

Notice that the initializer block ran twice — once for each new call — and always before the constructor body.

Why Use an Instance Initializer Block?

The most common reason is sharing initialization code across multiple constructors without duplicating it or creating a separate helper method. If every constructor needs to run the same setup logic, you can write it once in the IIB.

public class Counter {
    int count;
    String label;

    {
        count = 0;
        System.out.println("Counter initialized");
    }

    Counter() {
        label = "default";
    }

    Counter(String label) {
        this.label = label;
    }
}

Both constructors benefit from the shared count = 0 initialization without either one calling the other via this().

Tip: If you only have one constructor, an IIB does not add much value. It shines when you have two or more constructors and want DRY shared setup.

Execution Order: The Full Picture

Understanding exactly when each piece runs helps you avoid subtle bugs. Java follows this order when creating an object:

  1. The super() constructor chain runs first (all the way up to Object).
  2. Instance initializer blocks run in the order they appear in the source file.
  3. The constructor body runs.
public class Animal {
    Animal() {
        System.out.println("Animal constructor");
    }
}

public class Dog extends Animal {
    String breed;

    {
        breed = "Unknown";
        System.out.println("Dog initializer block");
    }

    Dog() {
        // implicit super() call happens first
        System.out.println("Dog constructor");
    }

    public static void main(String[] args) {
        new Dog();
    }
}

Output:

Animal constructor
Dog initializer block
Dog constructor

Note: super() is always the very first thing — even before the IIB. The JVM inserts the super() call implicitly if you don’t write it yourself.

Multiple Instance Initializer Blocks

You can have more than one IIB in a class. They all run, in top-to-bottom order, before the constructor.

public class Demo {

    {
        System.out.println("First initializer block");
    }

    {
        System.out.println("Second initializer block");
    }

    Demo() {
        System.out.println("Constructor");
    }

    public static void main(String[] args) {
        new Demo();
    }
}

Output:

First initializer block
Second initializer block
Constructor

Warning: Having many IIBs can make the flow harder to follow. Prefer keeping initialization logic in one block or in the constructor unless you have a clear reason to split it.

Instance Initializer vs Static Initializer

Java also has a static initializer block (static { ... }), which is easy to confuse with the IIB. Here is the key difference:

FeatureInstance Initializer BlockStatic Initializer Block
Syntax{ ... }static { ... }
RunsOnce per object creationOnce when class is loaded
AccessCan access instance fieldsCan only access static fields
Use caseShared instance setupOne-time class-level setup
public class Example {

    static int classCount;
    int id;

    static {
        classCount = 0;
        System.out.println("Static initializer");
    }

    {
        classCount++;
        id = classCount;
        System.out.println("Instance initializer, id = " + id);
    }

    Example() {
        System.out.println("Constructor, id = " + id);
    }

    public static void main(String[] args) {
        new Example();
        new Example();
    }
}

Output:

Static initializer
Instance initializer, id = 1
Constructor, id = 1
Instance initializer, id = 2
Constructor, id = 2

Instance Initializer vs Constructor

You might wonder: why not just put everything in the constructor? Here are the cases where the IIB has an edge:

  • Anonymous inner classes — anonymous classes cannot have named constructors, so the IIB is the only way to add initialization logic to them.
  • Shared setup across overloaded constructors — avoids repeating code or chaining constructors artificially.
// Anonymous inner class with an IIB
Runnable r = new Runnable() {
    {
        System.out.println("Anonymous class initialized");
    }

    @Override
    public void run() {
        System.out.println("Running");
    }
};
r.run();

Output:

Anonymous class initialized
Running

For most modern code, you can often replace anonymous inner classes with lambda expressions, but when you do need anonymous classes, the IIB is invaluable.

Under the Hood

When the Java compiler processes an instance initializer block, it copies the IIB code into every constructor in the class, right after the super() call. You can verify this with the javap tool.

So this source code:

class Foo {
    int x;

    { x = 10; }

    Foo() { }
    Foo(int extra) { x += extra; }
}

Is compiled as if you had written:

class Foo {
    int x;

    Foo() {
        super();
        x = 10;   // IIB code injected here
    }

    Foo(int extra) {
        super();
        x = 10;   // IIB code injected here too
        x += extra;
    }
}

This means there is no runtime overhead from using an IIB versus writing the code directly in each constructor — the bytecode is identical. It is purely a source-level convenience.

Note: Because the compiler inlines IIB code into every constructor, changes to the IIB affect all constructors automatically when you recompile. This makes refactoring safer — you only edit one place.

Common Pitfalls

  • Forgetting the execution order: IIBs run after super() but before the rest of the constructor body. If your IIB depends on a value set in the constructor, that value won’t be there yet.
  • Side effects in IIBs: Avoid I/O or slow operations in an IIB — it runs on every object creation and can hurt performance if the class is instantiated frequently.
  • Mistaking IIB for static block: A missing static keyword makes a world of difference. Double-check your braces.
  • Constructors — the primary place for object initialization logic and how IIBs fit alongside them
  • static Keyword — covers static initializer blocks and how class-level initialization works
  • this Keyword — using this() to chain constructors as an alternative to IIBs
  • Anonymous Inner Class — where IIBs are especially useful since anonymous classes have no named constructor
  • Classes & Objects — the broader picture of how Java objects are created and structured
  • Inheritance — explains the super() call that always precedes the IIB during object creation
Last updated June 13, 2026
Was this helpful?