EMZETT.
Login

Constructors

In short: A special method that’s automatically called when an object is created with new, to set its initial state.

In more detail: The constructor always carries the same name as the class and has no return type (not even void). If a class defines no constructor of its own, Java automatically creates an empty default constructor. Like regular methods, constructors can be defined multiple times with different parameters via overloading.

class Car {
    String color;
    Car(String color) {
        this.color = color;
    }
}

In Depth

As soon as a class defines its OWN constructors, the automatically generated default constructor is dropped entirely — a common beginner mistake is calling new Car() (with no arguments) even though only Car(String color) exists:

class Car {
    String color;
    int year;
 
    Car(String color) {
        this(color, 2024); // calls the other constructor - constructor chaining
    }
 
    Car(String color, int year) {
        this.color = color;
        this.year = year;
    }
}
 
Car c1 = new Car("Red");        // uses 2024 as the default year
Car c2 = new Car("Blue", 2019);

this(...) as the first line of a constructor calls another constructor of the SAME class — useful for setting default values without duplicating initialization logic. With inheritance, a subclass constructor automatically (or explicitly via super(...)) calls the superclass’s constructor before its own code runs — the object chain is thus always initialized “top to bottom”.

Constructors with inheritance

class Vehicle {
    String brand;
    Vehicle(String brand) {
        this.brand = brand;
        System.out.println("Vehicle constructor running");
    }
}
 
class Car extends Vehicle {
    int doors;
    Car(String brand, int doors) {
        super(brand); // MUST be the first line, otherwise a compiler error
        this.doors = doors;
        System.out.println("Car constructor running");
    }
}
 
new Car("VW", 4);
// Output:
// Vehicle constructor running
// Car constructor running

If the explicit super(...) call is missing, the compiler automatically inserts an implicit super() (with no arguments) as the first line — this fails if the superclass has no parameterless constructor, forcing an explicit call with matching arguments.

Initialization order in detail

Before the actual constructor code runs, this happens in order: (1) field initializers directly at declaration (int x = 5;), (2) instance initializer blocks ({ ... } with no method name), (3) the constructor body itself. With inheritance, this entire sequence is run completely for the superclass first, before the subclass takes its turn.

private constructors

A constructor doesn’t necessarily have to be public — a private constructor prevents code outside the class from calling new on it. This is the basis for the singleton pattern (exactly one instance of the class exists, created via its own static method instead of directly via new) and for pure utility classes with exclusively static methods (like Math), which shouldn’t be instantiated at all.

Records as a modern alternative

Since Java 16, there’s record as a compact alternative for simple, immutable data classes — constructor, getters, equals(), hashCode(), and toString() are all automatically generated, without having to be written out:

record Point(int x, int y) {}
 
Point p = new Point(3, 4); // constructor automatically generated
System.out.println(p.x()); // getter is named like the field, not getX()

For pure data holders with no complex logic, a record often replaces a whole classic class with a manually written constructor and getters — saves a considerable amount of code, but is only suitable when the objects are really meant to be immutable.

See also: Classes, Objects, this Keyword, Overloading, Inheritance