Skip to content
Chapter 09 · Core Java

Constructors In Depth ​

Constructors are one of the most heavily tested topics in Java interviews. Before you finish reading this article, you will have a clear answer to every common interview question about constructors, and more importantly, you will understand the reasoning behind each rule so you never have to memorize anything blindly.

What a Constructor Actually Does ​

Think about building a house. Before anyone can live in it, two things must happen: the house has to be physically built, and it has to be furnished with the basics so it is actually usable. A constructor does exactly the same two things for a Java object: it creates the instance and it initializes the instance variables.

Every time you write new SomeClass(), Java calls the constructor for that class. The constructor's job is to bring the object into a valid, initialized state so that the rest of your code can safely use it.

A constructor looks a lot like a method, and that similarity trips people up. But three rules make a constructor fundamentally different from any method:

  1. The constructor name must be identical to the class name.
  2. A constructor has no return type, not even void.
  3. A constructor cannot be declared static, final, abstract, or synchronized.

Does new create the object, or the constructor? A method is allowed to have the same name as the class, so new is what tells Java at runtime: call the constructor, not a method with that name. The constructor then creates and initializes the instance.

These rules exist for specific reasons, and interviewers like to check that you know them.


The Interview Questions You Must Know Cold ​

Why must the constructor name match the class name? ​

Java needs a fast, unambiguous way to identify constructors among all the other methods in a class. There might be hundreds of methods. The naming rule means the compiler can find the constructor instantly. No searching, no guessing.

There is a subtle trap here that interviewers use: a method can legally have the same name as its class. This is valid Java:

java
class Employee {
    // This is a constructor (no return type)
    Employee() {
        System.out.println("I am the constructor");
    }

    // This is a regular METHOD with the same name (has return type)
    void Employee() {
        System.out.println("I am a method, not a constructor");
    }
}

The presence or absence of a return type is the only thing distinguishing the two. A constructor has no return type. A method named Employee must declare void or some other type. This is why the "no return type" rule matters so deeply.

Why does a constructor have no return type? ​

When you call new Employee(), Java creates an Employee object and hands it back to you. The constructor implicitly returns the newly created instance. Because this return is always the object itself, there is no need to declare a return type. Java handles it automatically.

If you wrote Employee Employee() { } with a return type, Java would treat it as a regular method, not a constructor. The absence of a return type is the precise signal that tells the compiler "this is a constructor."

Why can constructors not be static? ​

Two separate reasons, both fundamental.

First, a static method can only access static variables. It has no concept of this, no reference to any particular object. But a constructor's entire purpose is to initialize instance variables on a specific object. If the constructor were static, it could not touch any instance variable. The constructor would be useless.

Second, constructor chaining through super() and this() requires an instance context. A static context has no this, so chaining would be impossible.

Why can constructors not be final? ​

The final keyword prevents a method from being overridden by a subclass. For final to make any sense, a method must first be inheritable. Constructors are never inherited, so they can never be overridden. Applying final to something that cannot be overridden is meaningless, and Java simply does not allow it.

Why are constructors not inherited? Because the inheritance rule for constructors would break the name rule. Imagine Employee had a constructor called Employee(). If it were inherited by Manager, that class would have a constructor named Employee inside it, but the rule says a constructor must have the same name as its own class. A constructor named Employee inside Manager would be constructing an Employee, not a Manager. The whole system would fall apart.

Why can constructors not be abstract? ​

An abstract method has no body. The class declaring it is forcing some subclass to provide the implementation. But for that to work, the subclass must inherit the abstract method, provide a body, and override it. Constructors are never inherited, so no subclass can ever implement a parent's constructor. The abstract concept simply does not apply.

Can an interface have a constructor? ​

No. The rule for a constructor is that it creates an instance of the class it belongs to. You can never write new SomeInterface(). Interfaces cannot be instantiated directly, so there is no scenario in which an interface constructor would run. Interfaces have no constructors.

Can constructors be overridden? ​

No. Since constructors are not inherited, they cannot be overridden. However, you can overload constructors: multiple constructors in the same class with different parameter lists. That is a completely different thing.


The Four Types of Constructors ​

Default Constructor ​

When you write a class and define no constructors at all, Java silently inserts a no argument constructor called the default constructor. You will not see it in your source file, but if you compile the class and look at the decompiled bytecode, it is right there.

java
class Calculation {
    // You wrote nothing here
}

// What Java actually compiles:
class Calculation {
    Calculation() {
        super(); // Java inserts this too
    }
}

Fields you did not initialize hold their zero values: int is 0, double is 0.0, boolean is false, any object reference is null. Strictly speaking, that zeroing is not done by the default constructor: the JVM zeroes the memory when new allocates the object, before any constructor runs. The default constructor only calls super() (and any field initializers you wrote run as part of it).

No Argument Constructor ​

A no argument constructor looks identical to the default constructor in structure, but you write it explicitly. The moment you write it yourself, you have the power to add initialization logic inside it.

java
class Calculation {
    String name;

    // No-arg constructor written explicitly
    Calculation() {
        this.name = "Default"; // your own initialization
        System.out.println("Calculation object created");
    }
}

Parameterized Constructor ​

A parameterized constructor accepts arguments so callers can supply specific values at construction time.

java
class Employee {
    private int employeeId;
    private String name;

    Employee(int employeeId, String name) {
        this.employeeId = employeeId; // this.employeeId = field, employeeId = parameter
        this.name = name;
    }
}

Employee emp = new Employee(101, "Priya");

Notice the use of this.employeeId. Without this, the line would be employeeId = employeeId, which assigns the parameter to itself and leaves the field untouched. The compiler does not warn you because the assignment is syntactically valid. This is one of the most common silent bugs beginners introduce.

Private Constructor ​

A private constructor means no code outside the class can call it, so nobody outside can create an object with new. The class keeps full control. It hands out objects through a public static method; the method must be static because the caller has no object yet to call it on.

java
class Calculation {
    private Calculation() { }                  // only this class can call it

    public static Calculation getInstance() {
        return new Calculation();              // allowed: we are inside the class
    }
}

Calculation c = Calculation.getInstance();    // the only way in from outside
// new Calculation();                         // compile error outside the class

This is the base of the Singleton pattern, where getInstance() is changed to always return the same single object (covered in the Singleton chapter).


The Vanishing Default Constructor ​

This catches so many developers by surprise. The default constructor exists only when you write zero constructors of your own. The moment you define any constructor, even just one parameterized constructor, Java stops providing the default.

java
class Calculation {
    String name;

    // You define ONE parameterized constructor
    Calculation(String name) {
        this.name = name;
    }
}

new Calculation("Priya"); // OK
new Calculation();        // compile error: constructor Calculation in class Calculation cannot be applied to given types

Java no longer provides the no argument constructor because you have taken over constructor definition yourself. If you still need both, you must write both explicitly:

java
class Calculation {
    String name;

    Calculation() {
        this.name = "Default";
    }

    Calculation(String name) {
        this.name = name;
    }
}

This matters in inheritance too. If a parent class has only a parameterized constructor and no no argument constructor, every child class must explicitly call super(arguments). You will see exactly why in the section on super().


Constructor Overloading ​

Like method overloading, a class can have several constructors with the same name but different parameter lists. new picks the one whose parameters match the arguments.

java
class Employee {
    String name;
    int employeeId;

    Employee(String name) {
        this.name = name;          // this.name = the field, name = the parameter
        this.employeeId = 0;
    }

    Employee(String name, int employeeId) {
        this.name = name;
        this.employeeId = employeeId;
    }
}

new Employee("Priya");        // calls the first constructor
new Employee("Priya", 101);   // calls the second

There is no constructor overriding, because constructors are never inherited.


Constructor Chaining with this() ​

When a class has multiple overloaded constructors, you often end up writing the same initialization logic in each one. Constructor chaining with this() lets you avoid that duplication by having one constructor call another.

java
class Calculation {
    String name;
    int id;
    String type;

    // Three-arg constructor: does all the real work
    Calculation(String name, int id, String type) {
        this.name = name;
        this.id = id;
        this.type = type;
    }

    // Two-arg constructor: supplies a default for type, then chains to three-arg
    Calculation(String name, int id) {
        this(name, id, "basic"); // calls three-arg constructor
    }

    // One-arg constructor: supplies defaults for id and type, then chains
    Calculation(int id) {
        this("DefaultName", id); // calls two-arg constructor
        // which in turn calls three-arg constructor
    }
}

When you call new Calculation(42), the chain runs: the one arg constructor calls the two arg constructor, which calls the three arg constructor, which sets all three fields. This is constructor chaining within the same class.


Constructor Chaining with super() ​

The this() call works within one class. super() works between a parent class and a child class.

Here is a critical fact that surprises many people: Java automatically inserts super() as the very first statement of every constructor that does not already have an explicit this() or super() call. You do not write it, but it is always there.

java
class Person {
    Person() {
        System.out.println("Person constructor runs");
    }
}

class Manager extends Person {
    Manager() {
        // Java silently inserts: super();
        System.out.println("Manager constructor runs");
    }
}

new Manager();

Output:

Person constructor runs
Manager constructor runs

The parent's constructor always runs before the child's constructor. This is not optional or configurable. Java enforces it because the child object includes all of the parent's fields, and those parent fields must be initialized before the child's constructor tries to use them.

If you have a three level hierarchy like Object -> Person -> Manager, the order is: Object constructor first, then Person, then Manager. Every class in Java ultimately inherits from Object, so Object's constructor is always the very first thing that runs.

The Parameterized Parent Problem ​

The automatic super() only works when the parent has a no argument constructor. The moment you give a parent class only a parameterized constructor, its no argument constructor vanishes (remember the vanishing default rule), and every child class must explicitly provide the arguments:

java
class Person {
    private int employeeId;

    Person(int employeeId) {
        this.employeeId = employeeId;
        // no no-arg constructor exists now
    }
}

class Manager extends Person {
    private int age;

    Manager(int employeeId, int age) {
        super(employeeId); // REQUIRED: tells Java how to construct the Person part
        this.age = age;    // Manager initializes its own fields
    }
}

If you forget super(employeeId), javac gives you:

error: constructor Person in class Person cannot be applied to given types;
  required: int
  found:    no arguments

(Eclipse phrases the same problem as "Implicit super constructor Person() is undefined".)

Java tried to insert the default super() automatically, found no no argument constructor in Person, and gave up. You must supply it yourself.

The division of responsibility is clean: the parent constructor initializes the parent's fields, and the child constructor initializes the child's own additional fields. Never reach into the parent's private fields from a child constructor. Use super(...) and let the parent handle its own initialization.


Putting It Together: A Complete Example ​

Here is a realistic example that demonstrates all the major constructor concepts together:

java
class Person {
    protected int employeeId;

    // Parameterized constructor in parent
    Person(int employeeId) {
        this.employeeId = employeeId;
        System.out.println("Person constructor: id = " + employeeId);
    }
}

class Manager extends Person {
    private int age;
    private String department;

    // Full constructor: initializes everything
    Manager(int employeeId, int age, String department) {
        super(employeeId);           // parent initializes its own field
        this.age = age;              // Manager initializes its own fields
        this.department = department;
        System.out.println("Manager constructor: age=" + age + " dept=" + department);
    }

    // Convenience constructor: supplies default department
    Manager(int employeeId, int age) {
        this(employeeId, age, "General"); // chains to full constructor
    }
}

Manager m1 = new Manager(101, 35, "Engineering");
// Output:
// Person constructor: id = 101
// Manager constructor: age=35 dept=Engineering

Manager m2 = new Manager(102, 28); // uses default department
// Output:
// Person constructor: id = 102
// Manager constructor: age=28 dept=General

Every concept covered in this article appears in that example: parameterized constructor, the vanishing default, super() to delegate parent initialization, and this() chaining.

Check yourself ​

  1. Name three ways a constructor differs from a method.
  2. When does Java add a default constructor, and when does it disappear?
  3. Why can a constructor not be final, static, or abstract?
  4. What does the compiler insert at the start of Manager() if you write neither this(...) nor super(...)? What happens if Person has only Person(int id)?
  5. For new Manager() where Manager extends Person, which constructor body runs first, and why?
  6. Can a constructor be private? Why would you do that? What does new do?
Answers
  1. Same name as the class, no return type (not even void), cannot be static/final/abstract/synchronized; also, constructors are not inherited.
  2. Only when the class declares no constructors at all. Writing any constructor removes it.
  3. final and abstract are about overriding, and constructors are never inherited, so they cannot be overridden. static makes no sense because a constructor initializes a specific new object (this).
  4. super();. If Person has no no-arg constructor, compilation fails: constructor Person in class Person cannot be applied to given types. Call super(id) explicitly.
  5. Person's. Java inserts super() as the first line of Manager(), so the parent part of the object is built before the child part.
  6. Yes, to stop outside code from creating objects; the class hands them out through a static method such as getInstance() (the base of Singleton). new tells Java to call a constructor rather than a method with the same name.