Java Constructors — Default, Parameterized, Copy & Chaining

3 minute read

A constructor is a special method that initializes an object when it’s created. It has the same name as the class and no return type.


Default Constructor

If you write no constructors, Java provides one:

class Employee {
    String name;
    double salary;
    // Implicit: Employee() { }
}

Employee e = new Employee();  // name=null, salary=0.0

Parameterized Constructor

class Employee {
    private String name;
    private double salary;

    public Employee(String name, double salary) {
        this.name = name;
        this.salary = salary;
    }
}

Employee e = new Employee("Alice", 95000);

Constructor Overloading

class Employee {
    private String name;
    private String department;
    private double salary;

    public Employee(String name, String department, double salary) {
        this.name = name;
        this.department = department;
        this.salary = salary;
    }

    public Employee(String name, double salary) {
        this(name, "General", salary);
    }

    public Employee(String name) {
        this(name, 50000);
    }
}

Constructor Chaining with this()

this(...) calls another constructor in the same class. Must be the first statement.

class Product {
    private String name;
    private double price;
    private int quantity;

    public Product(String name, double price, int quantity) {
        this.name = name;
        this.price = price;
        this.quantity = quantity;
    }

    public Product(String name, double price) {
        this(name, price, 0);  // default quantity = 0
    }

    public Product(String name) {
        this(name, 0.0);  // default price = 0
    }
}

Constructor Chaining with super()

super(...) calls a parent class constructor:

class Person {
    protected String name;

    public Person(String name) {
        this.name = name;
    }
}

class Employee extends Person {
    private double salary;

    public Employee(String name, double salary) {
        super(name);  // call Person's constructor
        this.salary = salary;
    }
}

If you don’t call super(...), Java automatically calls super() (no-arg). If the parent has no no-arg constructor, you’ll get a compile error.


Copy Constructor

Creates a new object as a copy of an existing one:

class Employee {
    private String name;
    private double salary;

    public Employee(String name, double salary) {
        this.name = name;
        this.salary = salary;
    }

    // Copy constructor
    public Employee(Employee other) {
        this.name = other.name;
        this.salary = other.salary;
    }
}

Employee original = new Employee("Alice", 95000);
Employee copy = new Employee(original);  // independent copy

Record Classes (Java 16+)

For simple data holders, use record — the constructor is generated automatically:

record Employee(String name, String department, double salary) { }

Employee e = new Employee("Alice", "Engineering", 95000);
System.out.println(e.name());       // Alice
System.out.println(e.salary());     // 95000
System.out.println(e);              // Employee[name=Alice, department=Engineering, salary=95000.0]

Records automatically provide: constructor, getters, equals(), hashCode(), toString().


Destructors in Java? No!

Java does not have destructors. Memory is managed by the garbage collector.

The finalize() method exists but is deprecated (since Java 9). Don’t use it.

For resource cleanup, use:

// try-with-resources (preferred)
try (FileReader reader = new FileReader("file.txt")) {
    // use reader
}  // automatically closed

// Or implement AutoCloseable
class DatabaseConnection implements AutoCloseable {
    @Override
    public void close() {
        System.out.println("Connection closed");
    }
}

Constructor Best Practices

  1. Validate input in constructors:
    public Employee(String name, double salary) {
        if (name == null || name.isBlank()) throw new IllegalArgumentException("Name required");
        if (salary < 0) throw new IllegalArgumentException("Salary must be non-negative");
        this.name = name;
        this.salary = salary;
    }
    
  2. Keep constructors simple — assign fields, validate, done.

  3. Use factory methods for complex creation logic:
    public static Employee createIntern(String name) {
        return new Employee(name, "Internship", 30000);
    }
    

Quick Exercises

  1. Create a BankAccount class with constructors for: full (name + balance), name-only (default balance 0), and copy.
  2. Create a Person → Student hierarchy with super() chaining.
  3. Rewrite a simple class as a record.

Summary

Constructor Type Purpose
Default Auto-provided if none defined
Parameterized Initialize with specific values
Overloaded Multiple ways to create objects
Copy Clone an existing object
this() Chain to another constructor
super() Chain to parent constructor
  • Java has no destructors — use try-with-resources for cleanup
  • Records auto-generate constructors for data classes

What’s Next?

Area 2 complete! Now let’s deep-dive into the first pillar: Understanding Encapsulation.

Updated: