Let's look at the order in which code is executed in initialization blocks (static and non-static), constructors, and initialization of static and non-static fields. We'll investigate what happens in practice, by executing code.

To start, we have a class with a full set of every possible element:


public class MyClass {
    static {
        System.out.println("Static Block #1.");
    }

    public static String staticField = setStaticField();

    public MyClass() {
        System.out.println("Constructor.");
    }

    static {
        System.out.println("Static Block #2.");
    }

    {
        System.out.println("Initialization Block #1.");
    }

    public String nonStaticField = setNonStaticField();

    {
        System.out.println("Initialization Block #2.");
    }

    private String setNonStaticField() {
        System.out.println("Non-static field.");
        return "nonStaticField";
    }

    private static String setStaticField() {
        System.out.println("Static field.");
        return "staticField";
    }

    public static void print() {
        System.out.println("print() method.");
    }
}

Now, alongside this class, we'll create another one with a main method and then run it:


public class Solution {
    public static void main(String args[]) {
        System.out.println("hello");
    }
}

The output includes nothing from the MyClass class. There were no calls to MyClass methods, so the class was not even loaded. Let's now try to call the static print() method of the MyClass class. Twice.


public class Solution {
    public static void main(String args[]) {
        MyClass.print();
        MyClass.print();
    }
}

Output:

Static Block #1.
Static field.
Static Block #2.
print() method.
print() method.

Only the static initialization blocks were executed and the static field was initialized. And this happened only once. That's because the class was already loaded when we made the second call to the print() method. Remember: static fields are initialized and initialization blocks are executed once upon the first interaction with the class.

Note that static blocks are executed and fields are initialized in the order they are declared.

Next, instead of calling a static method, let's try creating two objects of our class:


public class Solution {
    public static void main(String args[]) {
        new MyClass();
        System.out.println();
        new MyClass();
    }
}

Output:

Static Block #1.
Static field.
Static Block #2.
Initialization Block #1.
Non-static field.
Initialization Block #2.
Constructor.

Initialization Block #1.
Non-static field.
Initialization Block #2.
Constructor.

First, static blocks are executed and static fields are initialized once. After that, each time an object is created, the non-static blocks, fields, and a constructor are processed. The fields and initialization blocks are processed in the order of their declaration, but the constructor is processed at the end — no matter where it is declared.

Let's complicate the example — we'll take two classes, where one of them inherits the other:


public class ParentClass {
    static {
        System.out.println("Static Block #1 of the parent class.");
    }

    public static String parentStatic = setParentStatic();

    static {
        System.out.println("Static Block #2 of the parent class.");
    }

    {
        System.out.println("Initialization Block #1 of the parent class.");
    }

    public String parentNonStatic = setParentNonStatic();

    {
        System.out.println("Initialization Block #2 of the parent class.");
    }

    public ParentClass() {
        System.out.println("Constructor of the parent class.");
    }

    private String setParentNonStatic() {
        System.out.println("Non-static field of the parent class.");
        return "parentNonStatic";
    }

    private static String setParentStatic() {
        System.out.println("Static field of the parent class.");
        return "parentStatic";
    }

    public String setChildNonStatic1() {
        System.out.println("Non-static field of the child class #1.");
        return "childNonStatic2" + parentNonStatic;
    }
}
 
public class ChildClass extends ParentClass {
    static {
        System.out.println("Static Block #1 of the child class.");
    }

    public static String childStatic = setChildStatic();

    static {
        System.out.println("Static Block #2 of the child class.");
    }

    public String childNonStatic1 = setChildNonStatic1();

    {
        System.out.println("Initialization Block #1 of the child class.");
    }

    public String childNonStatic2 = setChildNonStatic2();

    {
        System.out.println("Initialization Block #2 of the child class.");
    }

    public ChildClass() {
        System.out.println("Constructor of the child class.");
    }

    private String setChildNonStatic2() {
        System.out.println("Non-static field of the child class #2.");
        return "childNonStatic";
    }

    private static String setChildStatic() {
        System.out.println("Static field of the child class.");
        return "childStatic";
    }
}

Let's create two objects of the child class:


public class Solution {
    public static void main(String[] args) {
        new ChildClass();
        System.out.println();
        new ChildClass();
    }
}

Output:

Static Block #1 of the parent class.
Static field of the parent class.
Static Block #2 of the parent class.
Static Block #1 of the child class.
Static field of the child class.
Static Block #2 of the child class.
Initialization Block #1 of the parent class.
Non-static field of the parent class.
Initialization Block #2 of the parent class.
Constructor of the parent class.
Non-static field of the child class #1.
Initialization Block #1 of the child class.
Non-static field of the child class #2.
Initialization Block #2 of the child class.
Constructor of the child class.

Initialization Block #1 of the parent class.
Non-static field of the parent class.
Initialization Block #2 of the parent class.
Constructor of the parent class.
Non-static field of the child class #1.
Initialization Block #1 of the child class.
Non-static field of the child class #2.
Initialization Block #2 of the child class.
Constructor of the child class.

From the new output, we see that the static blocks and variables of the parent class are processed before the static blocks and variables of the child class. It's the same with non-static blocks and variables and constructors: first the parent class, then the child class. To understand why this is necessary, take a look at the example of the childNonStatic1 field of the child class. A method of the parent class is used to initialize it, and that method in turn uses a variable of the parent class. That means that when the childNonStatic1 field is initialized, the parent class and its methods must already be loaded, and the variables of the parent class must be initialized.

In practice, you may not encounter classes that include all of these elements all at once, but it will be useful for you to remember what gets initialized before what. Oh, and this is also often asked about in job interviews.

undefined
14
Task
New Java Syntax, level 14, lesson 3
Locked
Set of plants
Create a HashSet with String elements. Add the following strings to it: watermelon banana cherry pear cantaloupe blackberry ginseng strawberry iris potato Display the contents of the collection, each element on a new line. Watch how the order of the entries has changed.
undefined
14
Task
New Java Syntax, level 14, lesson 3
Locked
Map of 10 pairs
Create a HashMap, and add 10 string pairs: watermelon - melon, banana - fruit, cherry - fruit, pear - fruit, cantaloupe - melon, blackberry - fruit, ginseng - root, strawberry - fruit, iris - flower, potato - tuber. Display the contents of the collection, each element on a new line. Example output:
undefined
14
Task
New Java Syntax, level 14, lesson 3
Locked
Values on the screen!
There is a HashMap. 10 different strings have been added to it. Display a list of values on the screen, each element on a new line.
undefined
14
Task
New Java Syntax, level 14, lesson 3
Locked
HashMap of Objects
There is a HashMap. 10 different object pairs have been added to it. Display the contents of the collection, each element on a new line. Example output: (here we just show one line): Sim - 5
undefined
14
Task
New Java Syntax, level 14, lesson 3
Locked
Display a list of keys
There is a HashMap. 10 different strings have been added to it. Display a list of keys on the screen, each element on a new line.
undefined
14
Task
New Java Syntax, level 14, lesson 3
Locked
Map of cats
There is a Cat class with a String name. Create a Map. Add 10 cats to the collection. The cat's name should be used as the key. Display the result on the screen, each element on a new line.