CodeGym /Courses /JAVA 25 SELF /Initialization blocks

Initialization blocks

JAVA 25 SELF
Level 15 , Lesson 4
Available

1. What are initialization blocks

In Java, there are two types of initialization blocks:

  • Non-static (instance) initialization blocks — executed every time a new object is created, immediately after field initialization and before the constructor is called.
  • Static initialization blocks — executed once when the class is loaded into memory (before the first object is created or any static fields/methods are accessed).

Non-static initialization block

Declared directly in the body of the class, without any keyword like static:

public class User {
    private String name;

    // Non-static initialization block
    {
        System.out.println("Executing non-static block!");
        name = "Default name";
    }

    public User() {
        System.out.println("Executing constructor!");
    }
}

Static initialization block

Declared with the static keyword:

public class Config {
    public static String appName;

    static {
        System.out.println("Executing static block!");
        appName = "My super application";
    }
}

2. Initialization order: who’s in charge?

In Java, the initialization order of class elements isn’t “random” but a strictly defined sequence. If you have ever tried to assemble IKEA furniture without the manual, you’ll understand why order matters: if you mix up the steps, you’ll get an art object instead of a wardrobe.

Initialization order:

  1. Static fields and static blocks — in the order they are declared in the class. Executed once when the class is loaded.
  2. Non-static fields and non-static blocks — in the order they are declared, for each new object created.
  3. Constructor — runs after all non-static initializations.

Schematic

+-------------------------------+
|   Class loading into the JVM  |
+-------------------------------+
| 1. Static fields              |
| 2. Static blocks              |
|         ↓                     |
|   Object creation             |
|         ↓                     |
| 3. Non-static fields          |
| 4. Non-static blocks          |
| 5. Constructor                |
+-------------------------------+

Example with output

Let’s write a class that shows us the order in which everything happens:

public class Demo {
    static String staticField = print("1. static field");

    static {
        print("2. static block");
    }

    String field = print("3. non-static field");

    {
        print("4. non-static block");
    }

    public Demo() {
        print("5. constructor");
    }

    static String print(String msg) {
        System.out.println(msg);
        return msg;
    }

    public static void main(String[] args) {
        System.out.println("Creating the first Demo object:");
        Demo d1 = new Demo();

        System.out.println("\nCreating the second Demo object:");
        Demo d2 = new Demo();
    }
}

What will appear on the screen?

1. static field
2. static block
Creating the first Demo object:
3. non-static field
4. non-static block
5. constructor

Creating the second Demo object:
3. non-static field
4. non-static block
5. constructor

Note: static parts (static) are executed only once—on the first access to the class. Everything that is not static runs every time an object is created.

3. Code examples: why initialization blocks are useful

When constructors aren’t enough

Sometimes part of the initialization needs to be shared by all constructors. For example, if a class has several constructors and you don’t want to duplicate the same initialization in each of them. In this case, it’s convenient to move it into a non-static block:

public class Person {
    private String id;
    private String name;

    {
        // This code will run before any constructor
        id = java.util.UUID.randomUUID().toString();
        System.out.println("Generating a unique id: " + id);
    }

    public Person() {
        System.out.println("Person() without parameters");
    }

    public Person(String name) {
        this.name = name;
        System.out.println("Person(String name)");
    }
}

Result: when any Person object is created, the id is generated first, then the appropriate constructor runs.

Initializing complex static data

A static block is often used to initialize “heavy” or complex static fields, for example, reading configuration from a file, creating collections, connecting to a database, etc.

public class Settings {
    public static final java.util.Map<String, String> DEFAULTS;

    static {
        DEFAULTS = new java.util.HashMap<>();
        DEFAULTS.put("theme", "light");
        DEFAULTS.put("language", "ru");
        System.out.println("Settings static block: default settings");
    }
}

4. Useful nuances

When to use initialization blocks

When to use

  • For common initialization required by all constructors.
  • For complex static data that cannot be expressed with a simple assignment.
  • For initializing static resources (for example, reading a config file at application startup).

When NOT to use

  • If a simple assignment or a constructor will do — use those.
  • Don’t “hide” business logic in initialization blocks — it makes the code harder to read and maintain.
  • If initialization depends on constructor parameters, use the constructor itself.

Don’t overuse initialization blocks

Initialization blocks are powerful but not the most commonly used tool. In most cases, a simple assignment or a constructor is enough. If a class has too many initialization blocks, the code becomes unreadable and hard to maintain.

Don’t use a non-static block for logic that depends on constructor parameters

You cannot use constructor parameters in a non-static block, because it runs BEFORE the constructor. If you need to initialize something based on parameters, do it in the constructor itself.

Static blocks and inheritance

Static initialization blocks are not inherited. Each class has its own static block. When a child class is loaded, the base class’s static block runs first, followed by the child class’s static block.

5. Common mistakes when working with initialization blocks

Error #1: Expecting a non-static block to see constructor parameters.
Many beginners try to use constructor parameters in a non-static block but get a compilation error or unexpected result. Remember: the non-static block runs BEFORE the constructor, which means there are no parameters yet.

Error #2: Too much logic in initialization blocks.
If complex logic appears in initialization blocks, the code becomes confusing. It’s better to do the main work in the constructor or separate methods.

Error #3: Multiple static blocks with different order.
If a class has several static blocks, they run in the order they are declared in the code, along with static fields. Sometimes this leads to unexpected results if, for example, one block depends on another’s result.

Error #4: Expecting the static block to run on each object creation.
static blocks run only once — when the class is loaded. If you expect re-initialization, it will not happen.

Error #5: Trying to access non-static fields from a static block.
Only static variables and methods are available in a static block. Attempting to access non-static (regular) fields will cause a compilation error.

1
Task
JAVA 25 SELF, level 15, lesson 4
Locked
First greeting from the loaded module 🚀
First greeting from the loaded module 🚀
1
Task
JAVA 25 SELF, level 15, lesson 4
Locked
Pet registration process at the shelter 🐾
Pet registration process at the shelter 🐾
1
Task
JAVA 25 SELF, level 15, lesson 4
Locked
Unraveling the system startup sequence 🧩
Unraveling the system startup sequence 🧩
1
Task
JAVA 25 SELF, level 15, lesson 4
Locked
Automatic ID assignment during user registration 🧑‍💻
Automatic ID assignment during user registration 🧑‍💻
1
Survey/quiz
Encapsulation, level 15, lesson 4
Unavailable
Encapsulation
Encapsulation principles
Comments
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION