Insights into Company
← Java

Constructors

Understand the idea. Compare it. Explain it. Test yourself.

Question 1 of 12

What is a constructor?

Solution and explanation

What it is

A constructor is a special block of code that runs automatically when an object is created with new. Its job is to initialise the new object so it starts in a valid state.

Rules that make it different from a method

  • Its name is exactly the class name.
  • It has no return type, not even void.
  • It is called once per object, by new (or by this()/super() from another constructor).
  • It cannot be static, final or abstract.
  • It can have any access modifier: public, protected, package-private or private.
public class Account {
    private final String accountNo;
    private final String holder;
    private double balance;

    public Account(String accountNo, String holder, double openingDeposit) {   // constructor
        if (openingDeposit < 1000) throw new IllegalArgumentException("Minimum opening deposit is ₹1000");
        this.accountNo = accountNo;
        this.holder = holder;
        this.balance = openingDeposit;
    }
}

Account acc = new Account("SB1001", "Kiran", 5000);

What happens on new

  1. Memory is allocated and fields get default values.
  2. The constructor is called; its first line calls the parent constructor (super()).
  3. Field initializers and instance blocks run.
  4. The rest of the constructor body runs.
  5. The reference to the fully initialised object is returned.

Note: if a method has the same name as the class but a return type (public void Account() {}), it is an ordinary method, not a constructor. The compiler allows it, which makes it a classic trick question.

Practice explaining this
Question 2 of 12

Why do we use a constructor?

Solution and explanation

Reasons

  1. Guarantee a valid initial state: required values must be supplied at creation, so no half-built object exists.
  2. Validation in one place: reject bad input before the object is used.
  3. Immutability: final fields can only be assigned in the constructor (or at declaration), which allows immutable objects.
  4. Dependency injection: an object receives its collaborators through the constructor (Spring's recommended style).
  5. Convenience: one line creates and initialises the object.

Without a constructor

User u = new User();
u.setEmail("ravi@example.com");
// forgot u.setName(...) → object is incomplete and may cause NullPointerException later

With a constructor

public final class User {
    private final String name;
    private final String email;

    public User(String name, String email) {
        this.name = Objects.requireNonNull(name, "name");
        if (!email.contains("@")) throw new IllegalArgumentException("Invalid email");
        this.email = email;
    }
}

User u = new User("Ravi", "ravi@example.com");   // always complete and valid

Constructor injection in Spring

@Service
public class OrderService {
    private final PaymentGateway gateway;          // final: cannot be changed later

    public OrderService(PaymentGateway gateway) {  // Spring passes the bean in
        this.gateway = gateway;
    }
}

This makes dependencies explicit, supports immutability and makes unit testing easy: pass a mock in the test.

Practice explaining this
Question 3 of 12

Does a constructor have a return type?

Solution and explanation

Answer

No. A constructor has no declared return type, not even void. It implicitly produces the newly created object, but you never write return value; in it. A bare return; to exit early is allowed.

public class Product {
    private String name;

    public Product(String name) {      // constructor: no return type
        if (name == null) return;      // allowed (exits early) but rarely good practice
        this.name = name;
    }

    public void Product() {            // NOT a constructor: it has a return type, so it is a method
        System.out.println("I am just a method named Product");
    }
}

Product p = new Product("Pen");   // calls the constructor
p.Product();                      // calls the method

Why no return type?

new is what creates and returns the object. The constructor only initialises the memory that new has already allocated, so it has nothing to return. Adding a return type turns it into an ordinary method, and then the compiler supplies a default constructor instead (if no other constructor exists).

Practice explaining this
Question 4 of 12

Can a constructor be private?

Solution and explanation

Answer

Yes. A private constructor can only be called from inside the class itself. It is used to control or prevent object creation.

Use 1: Singleton (exactly one instance)

public class AppConfig {
    private static final AppConfig INSTANCE = new AppConfig();
    private AppConfig() { /* load settings */ }
    public static AppConfig getInstance() { return INSTANCE; }
}

Use 2: Utility classes (no instance at all)

public final class DateUtils {
    private DateUtils() { throw new AssertionError("No instances"); }
    public static boolean isWeekend(LocalDate d) { return d.getDayOfWeek().getValue() >= 6; }
}

Use 3: Static factory methods with meaningful names

public class Money {
    private final long paise;
    private Money(long paise) { this.paise = paise; }

    public static Money ofRupees(long rupees) { return new Money(rupees * 100); }
    public static Money ofPaise(long paise)   { return new Money(paise); }
}
Money price = Money.ofRupees(499);

Use 4: Builder pattern

The class has a private constructor that takes the Builder; only Builder.build() can create it.

Use 5: Constructor chaining

A private constructor holds common initialisation code that public constructors call with this(...).

Effects

  • Other classes cannot write new AppConfig() (compile error).
  • The class cannot be subclassed from outside, because a subclass constructor must call a super constructor it can access.
  • Reflection can still call it with setAccessible(true); an enum singleton is protected even against that.
Practice explaining this
Question 5 of 12

What is a default constructor?

Solution and explanation

What it is

If a class declares no constructor at all, the compiler adds a default constructor: public (same access as the class), no parameters, and its only action is calling super().

public class Student {
    String name;      // default null
    int age;          // default 0
}

// The compiler effectively generates:
// public Student() { super(); }

Student s = new Student();   // works

Important: it disappears when you write any constructor

public class Student {
    String name;
    public Student(String name) { this.name = name; }
}

Student s = new Student();   // compile error: constructor Student() is undefined

If you still need a no-argument constructor, write it yourself:

public Student() { this("Unknown"); }

Why frameworks care

JPA/Hibernate entities and many serialization libraries (Jackson by default) create objects through a no-argument constructor and then set fields. That is why entities usually declare a protected or public no-arg constructor.

Default constructor vs no-arg constructor

  • Default constructor: generated by the compiler, only when you write none.
  • No-arg constructor: any constructor with no parameters, which you may write yourself with custom logic.
Practice explaining this
Question 6 of 12

What is a parameterized constructor?

Solution and explanation

What it is

A constructor that takes arguments, so each object can be initialised with different values at creation time.

public class Job {
    private final String title;
    private final String company;
    private final double minSalaryLpa;

    public Job(String title, String company, double minSalaryLpa) {
        this.title = title;
        this.company = company;
        this.minSalaryLpa = minSalaryLpa;
    }

    @Override public String toString() { return title + " at " + company + " (" + minSalaryLpa + " LPA+)"; }
}

Job j1 = new Job("Java Developer", "TCS", 6.5);
Job j2 = new Job("Data Analyst", "Flipkart", 12);
System.out.println(j1);   // Java Developer at TCS (6.5 LPA+)

this.field = parameter

When the parameter has the same name as the field, the parameter shadows the field. this.title refers to the field, title to the parameter. Forgetting this. (title = title;) assigns the parameter to itself and leaves the field null.

Many parameters? Use a builder

A constructor with six or more parameters of similar types is error-prone (new Job("TCS", "Java Developer", ...) swaps silently). Use the Builder pattern or a record:

public record JobPost(String title, String company, double minSalaryLpa) { }
JobPost p = new JobPost("Java Developer", "TCS", 6.5);   // canonical constructor generated
Practice explaining this
Question 7 of 12

What is constructor overloading?

Solution and explanation

What it is

Constructor overloading means a class has several constructors with different parameter lists (number, types or order of parameters). The compiler chooses one based on the arguments passed to new.

public class Pizza {
    private final String size;
    private final String crust;
    private final List<String> toppings;

    public Pizza() {
        this("Medium");                                 // delegates
    }

    public Pizza(String size) {
        this(size, "Classic");
    }

    public Pizza(String size, String crust) {
        this(size, crust, List.of("Cheese"));
    }

    public Pizza(String size, String crust, List<String> toppings) {   // the one that does the work
        this.size = size;
        this.crust = crust;
        this.toppings = List.copyOf(toppings);
    }
}

new Pizza();                                     // Medium, Classic, [Cheese]
new Pizza("Large");                              // Large, Classic, [Cheese]
new Pizza("Small", "Thin", List.of("Paneer", "Onion"));

Rules

  • Parameter lists must differ; differing only by parameter names is not allowed.
  • Access modifiers can differ between overloads.
  • Resolution happens at compile time (static polymorphism).

Good practice

Let the shorter constructors call the most complete one with this(...) (telescoping), so validation and assignment live in one place. Real examples: new ArrayList<>(), new ArrayList<>(100) and new ArrayList<>(otherCollection).

Practice explaining this
Question 8 of 12

What is constructor chaining?

Solution and explanation

What it is

Constructor chaining is calling one constructor from another:

  • this(...) calls another constructor of the same class.
  • super(...) calls a constructor of the parent class.

It avoids duplicated initialisation code and makes sure parent parts of an object are initialised before child parts.

Within the same class

public class Employee {
    private final String name;
    private final String dept;
    private final double salary;

    public Employee(String name) { this(name, "Trainee"); }
    public Employee(String name, String dept) { this(name, dept, 25000); }
    public Employee(String name, String dept, double salary) {
        this.name = name; this.dept = dept; this.salary = salary;
    }
}

Across the hierarchy

class Vehicle {
    Vehicle(String reg) { System.out.println("Vehicle " + reg); }
}
class Car extends Vehicle {
    Car(String reg) {
        super(reg);                                  // must be first
        System.out.println("Car ready");
    }
}
class ElectricCar extends Car {
    ElectricCar(String reg) {
        super(reg);
        System.out.println("Battery checked");
    }
}
new ElectricCar("HR26AB1234");
Vehicle HR26AB1234
Car ready
Battery checked

Construction always runs from the top of the hierarchy (Object) down to the actual class.

Rules

  • this(...) or super(...) must be the first statement of the constructor.
  • A constructor cannot contain both.
  • If you write neither, the compiler inserts super(). If the parent has no no-arg constructor, that is a compile error.
  • Recursive chaining (A() calls this(1) which calls this()) is a compile error.
Practice explaining this
Question 9 of 12

What is this()?

Solution and explanation

What it is

this() (with parentheses) calls another constructor of the same class. It is used for constructor chaining.

public class Rectangle {
    private final int width, height;

    public Rectangle() { this(1, 1); }            // calls Rectangle(int, int)
    public Rectangle(int side) { this(side, side); }
    public Rectangle(int width, int height) {
        if (width <= 0 || height <= 0) throw new IllegalArgumentException("Sides must be positive");
        this.width = width;
        this.height = height;
    }
}

Rules

  • Can only appear inside a constructor.
  • Must be the first statement.
  • Cannot be combined with super() in the same constructor (the chained constructor will call super() itself).

this() vs this

this()this
Calls another constructor of the same classReference to the current object
Only in constructors, first lineIn any instance method or constructor
Used for chainingUsed to access fields (this.name = name), pass the current object (register(this)), return it for fluent APIs (return this;)
public class QueryBuilder {
    private final StringBuilder sql = new StringBuilder("SELECT * FROM jobs");
    public QueryBuilder where(String cond) { sql.append(" WHERE ").append(cond); return this; }   // fluent
}
Practice explaining this
Question 10 of 12

What is super()?

Solution and explanation

What it is

super() calls a constructor of the immediate parent class. It makes sure the inherited part of the object is initialised before the child adds its own state.

class Person {
    protected final String name;
    Person(String name) { this.name = name; }
}

class Employee extends Person {
    private final String empId;
    Employee(String name, String empId) {
        super(name);           // initialise the Person part first
        this.empId = empId;
    }
}

Rules

  • Must be the first statement of the constructor.
  • If you do not write super(...) or this(...), the compiler inserts super() (no arguments).
  • If the parent has only parameterised constructors, you must call one explicitly, otherwise compile error: "constructor Person in class Person cannot be applied to given types".

The super keyword without parentheses

super. accesses the parent's members:

class Manager extends Employee {
    @Override
    public double salary() {
        return super.salary() + 20000;        // call the parent's version and extend it
    }
}
super()super.
Calls parent constructorCalls parent method or accesses parent field
Only first line of a constructorAnywhere in instance code
Practice explaining this

Showing questions 1–10 of 12