Java Constructors: Types, Overloading & Destructors
Last Updated on: 25th Oct 2025 13:42:18 PM
Welcome to the complete beginner-friendly tutorial on Constructors in Java — one of the most important concepts in Object-Oriented Programming (OOP)!
What is a Constructor?
A constructor is a special method in a class that is automatically called when an object is created using the new keyword.
Purpose:
-
Initialize object properties (fields)
-
Set default or custom values
-
Allocate resources
Key Features of Constructors
|
Feature |
Description |
|---|---|
|
Name |
Same as the class name |
|
Return Type |
None (not even void) |
|
Called |
Automatically with new |
|
Can be overloaded |
Yes |
|
Can call other constructors |
Using this() |
|
Cannot be static, final, or abstract |
Belongs to object, not class |
Types of Constructors in Java
There are three main types of constructors in Java:
-
Default Constructor
-
Created automatically by the compiler if no constructor is defined.
-
Initializes object with default values (0, null, false, etc.)..
-
-
No-Argument Constructor
-
Created by the programmer explicitly.
-
Used to perform custom initialization or display a message.
-
-
Parameterized Constructor
-
Takes parameters to initialize object with specific values.
-
-
Copy Constructor (user-defined)
-
Used to copy data from one object to another.
-
Not built-in like in C++, but can be implemented manually.
-
Real-Life Example: Student Enrollment System
Think of a university registration desk:
Some students register with basic info → Default Constructor
Some with full details → Parameterized Constructor
Some are transfers (copied from another record) → Copy Constructor
1. Default Constructor
class Student {
String name;
int age;
String course;
// Default Constructor
Student() {
name = "Unknown";
age = 18;
course = "General";
System.out.println("Default student created.");
}
void display() {
System.out.println("Name: " + name + ", Age: " + age + ", Course: " + course);
}
}
Usage:
Student s1 = new Student(); // Default constructor called
s1.display();
Output:
Default student created.
Name: Unknown, Age: 18, Course: General
2. Parameterized Constructor
class Student {
String name;
int age;
String course;
// Parameterized Constructor
Student(String name, int age, String course) {
this.name = name;
this.age = age;
this.course = course;
System.out.println("Custom student enrolled.");
}
void display() {
System.out.println("Name: " + name + ", Age: " + age + ", Course: " + course);
}
}
Usage:
Student s2 = new Student("Alice", 20, "Computer Science");
s2.display();
Output:
Custom student enrolled.
Name: Alice, Age: 20, Course: Computer Science
3. Copy Constructor
class Student {
String name;
int age;
String course;
// Parameterized Constructor
Student(String name, int age, String course) {
this.name = name;
this.age = age;
this.course = course;
}
// Copy Constructor
Student(Student other) {
this.name = other.name;
this.age = other.age;
this.course = other.course;
System.out.println("Student record copied.");
}
void display() {
System.out.println("Name: " + name + ", Age: " + age + ", Course: " + course);
}
}
Usage:
Student s1 = new Student("Bob", 22, "Mathematics");
Student s3 = new Student(s1); // Copy constructor
s3.display();
Output:
Student record copied.
Name: Bob, Age: 22, Course: Mathematics
Constructor Overloading
Constructor Overloading = Having multiple constructors in the same class with different parameter lists.
Real-Life Example: Pizza Order System
|
Order Type |
Constructor Used |
|---|---|
|
Just size |
Pizza("Large") |
|
Size + toppings |
Pizza("Medium", "Pepperoni") |
|
Full custom |
Pizza("Small", "Veggie", "Thin") |
Example: Constructor Overloading
class Pizza {
String size;
String toppings;
String crust;
double price;
// Constructor 1: Size only
Pizza(String size) {
this.size = size;
this.toppings = "Cheese";
this.crust = "Regular";
this.price = getBasePrice();
System.out.println("Basic pizza: " + size);
}
// Constructor 2: Size + Toppings
Pizza(String size, String toppings) {
this.size = size;
this.toppings = toppings;
this.crust = "Regular";
this.price = getBasePrice() + 2.0;
System.out.println("Pizza with " + toppings);
}
// Constructor 3: Full custom
Pizza(String size, String toppings, String crust) {
this.size = size;
this.toppings = toppings;
this.crust = crust;
this.price = getBasePrice() + 2.0 + 1.5;
System.out.println("Fully custom pizza!");
}
double getBasePrice() {
return switch (size) {
case "Small" -> 8.99;
case "Medium" -> 10.99;
case "Large" -> 12.99;
default -> 10.99;
};
}
void display() {
System.out.printf("Pizza: %s, %s, %s crust, $%.2f%n",
size, toppings, crust, price);
}
}
Main Class:
public class PizzaShop {
public static void main(String[] args) {
Pizza p1 = new Pizza("Large"); // Constructor 1
Pizza p2 = new Pizza("Medium", "Pepperoni"); // Constructor 2
Pizza p3 = new Pizza("Small", "Veggie", "Thin"); // Constructor 3
p1.display();
p2.display();
p3.display();
}
}
Output:
Basic pizza: Large
Pizza with Pepperoni
Fully custom pizza!
Pizza: Large, Cheese, Regular crust, $12.99
Pizza: Medium, Pepperoni, Regular crust, $12.99
Pizza: Small, Veggie, Thin crust, $12.49
this() – Constructor Chaining
Call one constructor from another to avoid code duplication.
class Employee {
String name;
int id;
double salary;
// Full constructor
Employee(String name, int id, double salary) {
this.name = name;
this.id = id;
this.salary = salary;
}
// Overloaded: name and id only
Employee(String name, int id) {
this(name, id, 50000.0); // Reuse full constructor
System.out.println("Default salary applied.");
}
}
Destructors in Java? → NO!
|
Language |
Destructor? |
Memory Management |
|---|---|---|
|
C++ |
Yes (~ClassName()) |
Manual |
|
Java |
No |
Garbage Collector (GC) |
Java Uses Garbage Collection
-
Automatically frees memory when object is no longer referenced
-
You cannot predict when GC runs
-
No need for destructors
finalize() Method (Deprecated!)
@Override
protected void finalize() throws Throwable {
System.out.println("Object is being cleaned up!");
}
Never rely on it. Use try-with-resources or clean-up methods instead.
Full Example: All Types + Overloading
class BankAccount {
String holder;
long accountNumber;
double balance;
String type;
// 1. Default Constructor
BankAccount() {
holder = "Unknown";
accountNumber = 0;
balance = 0.0;
type = "Savings";
System.out.println("Default account created.");
}
// 2. Parameterized: Holder + Balance
BankAccount(String holder, double balance) {
this.holder = holder;
this.accountNumber = System.currentTimeMillis();
this.balance = balance;
this.type = "Savings";
System.out.println("Account for " + holder + " created.");
}
// 3. Full Parameterized
BankAccount(String holder, long accountNumber, double balance, String type) {
this.holder = holder;
this.accountNumber = accountNumber;
this.balance = balance;
this.type = type;
System.out.println("Premium account created.");
}
// 4. Copy Constructor
BankAccount(BankAccount other) {
this.holder = other.holder;
this.accountNumber = other.accountNumber + 1000;
this.balance = other.balance;
this.type = other.type;
System.out.println("Account duplicated for branch transfer.");
}
void display() {
System.out.printf("Holder: %s, Acc: %d, Balance: $%.2f, Type: %s%n",
holder, accountNumber, balance, type);
}
}
Main Class:
public class Bank {
public static void main(String[] args) {
BankAccount a1 = new BankAccount(); // Default
BankAccount a2 = new BankAccount("Alice", 5000.0); // Parameterized
BankAccount a3 = new BankAccount("Bob", 123456, 10000, "Current"); // Full
BankAccount a4 = new BankAccount(a2); // Copy
a1.display();
a2.display();
a3.display();
a4.display();
}
}
Sample Output:
Default account created.
Account for Alice created.
Premium account created.
Account duplicated for branch transfer.
Holder: Unknown, Acc: 0, Balance: $0.00, Type: Savings
Holder: Alice, Acc: 1712345678901, Balance: $5000.00, Type: Savings
Holder: Bob, Acc: 123456, Balance: $10000.00, Type: Current
Holder: Alice, Acc: 1712345679901, Balance: $5000.00, Type: Savings
Summary Table
|
Constructor Type |
Parameters |
Use Case |
|---|---|---|
|
Default |
None |
Basic object with defaults |
|
Parameterized |
1+ args |
Custom initialization |
|
Copy |
Object |
Duplicate object |
|
Overloading |
Multiple |
Flexible object creation |
|
Feature |
Java |
|---|---|
|
Destructor |
Not supported |
|
Memory Cleanup |
Garbage Collector |
|
finalize() |
Deprecated |
Common Interview Questions
|
Question |
Answer |
|---|---|
|
Can constructor return a value? |
No |
|
Can we overload constructors? |
Yes |
|
What if no constructor is written? |
Java adds default constructor |
|
Can constructor be private? |
Yes (for Singleton pattern) |
|
Can we call constructor explicitly? |
Only via this() |
Practice Exercise
Create a MobilePhone class with:
-
Default constructor
-
Parameterized (brand, model, price)
-
Copy constructor
-
Overloaded constructor (brand, model)
-
display() method
Test all 4 constructors.
Final Words
You’ve mastered:
-
All types of constructors
-
Constructor overloading
-
Copy constructor
-
Why no destructors in Java
-
Real-world examples (Student, Pizza, Bank)
Constructors = Object Initialization Engine
Garbage Collector = Automatic Cleanup Crew
Keep coding! ![]()