Back to Blog
Java

Java Constructor Initialization Block: Order and Use

java constructor initialization block: Learn how Java constructor initialization blocks work, their execution order relative to constructors, and when to use instance...

instance initialization blockJava constructorsstatic initialization blockobject lifecycleanonymous classes
Diagram showing execution order of static blocks, instance initialization blocks, and constructors in Java.

The Java constructor initialization block, often called an instance initializer block, is a block of code that runs before the constructor body when an object is created. It provides a way to share initialization logic across multiple constructors without duplicating code. Understanding its execution order and interaction with static blocks and constructors is essential for writing predictable object initialization.

Instance Initialization Blocks in Java

An instance initialization block is a pair of curly braces placed directly inside a class body, outside any method or constructor. It runs every time an instance of the class is created, just before the constructor body executes. Here is the basic syntax:

public class Example { { System.out.println("Instance initializer block"); } public Example() { System.out.println("Constructor"); } }

When you call new Example(), the output is:

Instance initializer block
Constructor

The block is compiled into every constructor of the class. If the class has multiple constructors, the block runs before each one. This makes it a natural place for logic that must be executed regardless of which constructor is used.

Execution Order: Static Blocks, Instance Blocks, and Constructors

Java defines a strict order for initialization when a class is loaded and when objects are created. Static initialization blocks run once when the class is first loaded, before any object exists. Instance initialization blocks run before the constructor body for each new object. The full order is:

  1. Static initialization blocks, in the order they appear in the source.
  2. Instance initialization blocks, in the order they appear.
  3. The constructor body.

Consider this example:

public class OrderDemo { static { System.out.println("Static block"); } { System.out.println("Instance block 1"); } { System.out.println("Instance block 2"); } public OrderDemo() { System.out.println("Constructor"); } }

Creating two instances produces:

Static block
Instance block 1
Instance block 2
Constructor
Instance block 1
Instance block 2
Constructor

The static block runs only once, while the instance blocks run before every constructor call. This order is defined by the Java Language Specification and is consistent across all standard Java implementations.

Block typeWhen it runsNumber of times
Static initialization blockWhen the class is loadedOnce
Instance initialization blockBefore each constructor callOnce per object
Constructor bodyAfter instance blocksOnce per object

Where Instance Initialization Blocks Are Useful

Instance initializer blocks are most useful when you need to perform the same initialization steps for every constructor. For example, when a class has several constructors that all need to set up a logger or a shared resource:

public class Service { private final Logger logger; { logger = LoggerFactory.getLogger(Service.class); } public Service() { // default configuration } public Service(String name) { // named configuration } }

Without the instance block, you would have to assign the logger in each constructor. The block keeps that logic in one place.

Another common use is in anonymous classes, which cannot declare a constructor. An instance initializer block is the only way to run custom initialization logic when an anonymous class instance is created:

Runnable task = new Runnable() { { System.out.println("Anonymous instance created"); } @Override public void run() { // ... } };

Common Mistakes and Pitfalls

Instance initialization blocks can introduce subtle bugs if you do not consider their position relative to field initializers. Field initializers and instance blocks run in the order they appear in the source. If an instance block reads a field that is assigned later, it sees the default value.

public class Misorder { int value = 10; { System.out.println(value); // prints 0, not 10 } }

Because the instance block appears before the field initializer, value is still 0 when the block runs. To avoid this, place instance blocks after the field declarations they depend on.

Another pitfall is using instance blocks for logic that depends on constructor parameters. Instance blocks have no access to constructor arguments, so any parameter-dependent initialization must happen inside the constructor itself. Trying to use an instance block for that purpose will lead to compile-time errors or incorrect behavior.

Runtime Cost and Maintainability

From a runtime perspective, instance initialization blocks do not add a separate method call. The compiler inlines the block code into each constructor, so there is no extra invocation overhead. The cost is simply the execution of the statements themselves, which is the same as if you had written them directly in the constructor.

The maintainability concern is more significant. Instance blocks are easy to overlook because they are not visually associated with any constructor. If you use them for complex logic, future readers may not realize why certain fields are set before the constructor runs. Prefer constructors for logic that is specific to a particular construction path, and reserve instance blocks for truly common initialization that must run for every instance.

Initialization Blocks in Anonymous Classes and Inner Classes

Anonymous classes have no constructor name, so an instance initializer block is the only way to run setup code at creation time. This is particularly useful when you need to initialize fields or capture values in an anonymous class instance. For example:

Map<String, String> config = new HashMap<>() { { put("host", "localhost"); put("port", "8080"); } };

This pattern is common for creating small, one-off maps with initial values. The same approach works for inner classes, where the instance block runs after the enclosing instance is established.

Instance Initialization Blocks and Exception Handling

Instance initializer blocks can throw checked exceptions, but the constructor must declare or handle them. Since the block is inlined into the constructor, any checked exception thrown by the block must be declared in the constructor's throws clause. For example:

public class Resource { { if (!openConnection()) { throw new IllegalStateException("Cannot open connection"); } } public Resource() throws IllegalStateException { // constructor body } }

If the block throws a checked exception, the constructor must declare it. This can make constructors appear to throw exceptions that are not directly visible in their body, so document the behavior clearly.

Instance initialization blocks are a legitimate part of Java, but they should be used with care. They solve a real problem when multiple constructors share initialization logic, and they are indispensable for anonymous classes. The key is to understand the execution order, keep the blocks simple, and avoid placing them where they depend on fields that are not yet initialized.

java constructor initialization block: Practical Usage and C | RYUSLOG DEV