Constructors and Destructors

Difficulty: Beginner

Question

What is a constructor? Explain constructor overloading and chaining, and does Java have destructors?

Answer

A constructor is a special method that runs automatically when an object is created, and its job is to put the new object into a valid initial state. Think of it as the setup crew that arrives at a new hotel room before the guest: make the bed, stock the fridge, check the lights. Without a constructor, you would have to remember to call an init method every time, and forgetting it would leave you with a half-built object.

The rules in Java: a constructor has the same name as the class, has no return type (not even void), and cannot be static, final, or abstract. If you write no constructor at all, the compiler generates a default no-argument constructor. The moment you write any constructor yourself, the compiler stops generating the default one, and that is a classic gotcha: adding a parameterised constructor can break code that calls new Employee().

Constructor overloading means providing several constructors with different parameter lists, so callers can create objects in different ways. Constructor chaining is when one constructor calls another to avoid duplicating initialisation logic. Within the same class you use this(...), and to call the parent's constructor you use super(...). Either call must be the first statement in the constructor. If you do not write super(...) yourself, the compiler inserts super() automatically, and that is why a parent class without a no-argument constructor forces every child constructor to call super with arguments explicitly.

A copy constructor takes an object of the same class and copies its fields. Java has no built-in one (unlike C++), so you write it yourself when you need deep copies. Also, a constructor can be private to block outside instantiation, as with singletons and utility classes.

Now, destructors. C++ has them: a destructor is a method named with a tilde, like ~Guard(), that runs deterministically when an object goes out of scope or is deleted. C++ uses this for RAII, the pattern where a resource such as a file, lock, or memory is acquired in the constructor and released in the destructor, so cleanup is automatic even when exceptions occur.

Java has no destructors. Memory is reclaimed by the garbage collector at an unpredictable time. There was a method called finalize(), but it is unreliable, can resurrect objects, hurts performance, and has been deprecated for removal since Java 18. For releasing non-memory resources in Java, implement AutoCloseable and use try-with-resources, which calls close() deterministically. Python is similar: __del__ exists but is unreliable, and context managers with the with statement are the correct tool.

If you want to impress, mention that C++ virtual destructors matter when deleting a derived object through a base pointer, which is covered in the virtual function question, and that an object in Java is not fully constructed until its constructor returns, so calling overridable methods from a constructor is dangerous.

Code examples

Constructor overloading and chaining

class Employee {
    String name;
    int salary;

    Employee() {
        this("Unknown", 0);
        System.out.println("default");
    }
    Employee(String name) {
        this(name, 10000);
        System.out.println("one-arg");
    }
    Employee(String name, int salary) {
        this.name = name;
        this.salary = salary;
        System.out.println("two-arg");
    }
}

public class ChainDemo {
    public static void main(String[] args) {
        new Employee();
        System.out.println("---");
        new Employee("Asha");
    }
}

The chained constructor finishes first, so the two-arg body prints before the caller body.

C++ destructor and RAII

#include <iostream>
using namespace std;

class Guard {
public:
    Guard()  { cout << "acquire\n"; }
    ~Guard() { cout << "release\n"; }
};

int main() {
    cout << "start\n";
    {
        Guard g;
        cout << "working\n";
    }
    cout << "end\n";
}

Java try-with-resources as the destructor substitute

class Res implements AutoCloseable {
    Res() { System.out.println("open"); }
    public void close() { System.out.println("close"); }
}

public class CloseDemo {
    public static void main(String[] args) {
        try (Res r = new Res()) {
            System.out.println("use");
        }
    }
}

Key points

Concepts covered

constructor, destructor, constructor-chaining, RAII, garbage-collection