Java Constructors - Complete Guide
Introduction to Constructors
Constructors are special methods in Java that are used to initialize objects when they are created. They have the same name as the class and don't have a return type, not even void.
Constructors ensure that objects are properly initialized with valid state before they are used, which is crucial for writing robust and reliable object-oriented programs.
Types of Constructors
Java supports several types of constructors, each serving different purposes in object initialization.
Example
public class ConstructorTypes {
// Instance variables
private String name;
private int age;
private double salary;
// 1. Default constructor (no-args)
public ConstructorTypes() {
this.name = "Unknown";
this.age = 0;
this.salary = 0.0;
System.out.println("Default constructor called");
}
// 2. Parameterized constructor
public ConstructorTypes(String name, int age, double salary) {
this.name = name;
this.age = age;
this.salary = salary;
System.out.println("Parameterized constructor called");
}
// 3. Copy constructor
public ConstructorTypes(ConstructorTypes other) {
this.name = other.name;
this.age = other.age;
this.salary = other.salary;
System.out.println("Copy constructor called");
}
// 4. Constructor with validation
public ConstructorTypes(String name, int age) {
if (age < 0) {
throw new IllegalArgumentException("Age cannot be negative");
}
this.name = name;
this.age = age;
this.salary = 0.0;
System.out.println("Validated constructor called");
}
// 5. Private constructor (for singleton pattern)
private ConstructorTypes(String name) {
this.name = name;
this.age = 0;
this.salary = 0.0;
System.out.println("Private constructor called");
}
// Factory method to use private constructor
public static ConstructorTypes createWithName(String name) {
return new ConstructorTypes(name);
}
// Method to display object state
public void display() {
System.out.println("Name: " + name);
System.out.println("Age: " + age);
System.out.println("Salary: " + salary);
}
// Main method to demonstrate constructors
public static void main(String[] args) {
System.out.println("=== Constructor Demonstration ===\n");
// Default constructor
ConstructorTypes obj1 = new ConstructorTypes();
obj1.display();
System.out.println();
// Parameterized constructor
ConstructorTypes obj2 = new ConstructorTypes("Alice", 30, 50000.0);
obj2.display();
System.out.println();
// Copy constructor
ConstructorTypes obj3 = new ConstructorTypes(obj2);
obj3.display();
System.out.println();
// Validated constructor
try {
ConstructorTypes obj4 = new ConstructorTypes("Bob", 25);
obj4.display();
} catch (IllegalArgumentException e) {
System.out.println("Error: " + e.getMessage());
}
System.out.println();
// Try invalid age
try {
ConstructorTypes obj5 = new ConstructorTypes("Charlie", -5);
obj5.display();
} catch (IllegalArgumentException e) {
System.out.println("Error: " + e.getMessage());
}
System.out.println();
// Using factory method with private constructor
ConstructorTypes obj6 = ConstructorTypes.createWithName("David");
obj6.display();
}
}
Output
=== Constructor Demonstration === Default constructor called Name: Unknown Age: 0 Salary: 0.0 Parameterized constructor called Name: Alice Age: 30 Salary: 50000.0 Copy constructor called Name: Alice Age: 30 Salary: 50000.0 Validated constructor called Name: Bob Age: 25 Salary: 0.0 Error: Age cannot be negative Private constructor called Name: David Age: 0 Salary: 0.0
Constructor Chaining and Overloading
Constructors can call other constructors within the same class using this() keyword, enabling code reuse and flexible object initialization.
Example
public class ConstructorChaining {
private String name;
private int age;
private String department;
private double salary;
// Default constructor
public ConstructorChaining() {
this("Unknown", 0); // Calls 2-parameter constructor
System.out.println("Default constructor completed");
}
// 2-parameter constructor
public ConstructorChaining(String name, int age) {
this(name, age, "Undefined"); // Calls 3-parameter constructor
System.out.println("2-parameter constructor completed");
}
// 3-parameter constructor
public ConstructorChaining(String name, int age, String department) {
this(name, age, department, 0.0); // Calls 4-parameter constructor
System.out.println("3-parameter constructor completed");
}
// 4-parameter constructor (main constructor)
public ConstructorChaining(String name, int age, String department, double salary) {
if (age < 0) {
throw new IllegalArgumentException("Age cannot be negative");
}
if (salary < 0) {
throw new IllegalArgumentException("Salary cannot be negative");
}
this.name = name;
this.age = age;
this.department = department;
this.salary = salary;
System.out.println("4-parameter constructor completed");
}
// Copy constructor
public ConstructorChaining(ConstructorChaining other) {
this(other.name, other.age, other.department, other.salary);
System.out.println("Copy constructor completed");
}
public void display() {
System.out.println("Name: " + name);
System.out.println("Age: " + age);
System.out.println("Department: " + department);
System.out.println("Salary: $" + salary);
}
public static void main(String[] args) {
System.out.println("=== Constructor Chaining Demonstration ===\n");
System.out.println("1. Default constructor:");
ConstructorChaining obj1 = new ConstructorChaining();
obj1.display();
System.out.println("\n2. 2-parameter constructor:");
ConstructorChaining obj2 = new ConstructorChaining("Alice", 30);
obj2.display();
System.out.println("\n3. 3-parameter constructor:");
ConstructorChaining obj3 = new ConstructorChaining("Bob", 25, "Engineering");
obj3.display();
System.out.println("\n4. 4-parameter constructor:");
ConstructorChaining obj4 = new ConstructorChaining("Charlie", 35, "Sales", 75000.0);
obj4.display();
System.out.println("\n5. Copy constructor:");
ConstructorChaining obj5 = new ConstructorChaining(obj4);
obj5.display();
System.out.println("\n6. Invalid constructor call:");
try {
ConstructorChaining obj6 = new ConstructorChaining("David", -5, "HR", 50000.0);
obj6.display();
} catch (IllegalArgumentException e) {
System.out.println("Error: " + e.getMessage());
}
}
}
Output
=== Constructor Chaining Demonstration === 1. Default constructor: 4-parameter constructor completed 3-parameter constructor completed 2-parameter constructor completed Default constructor completed Name: Unknown Age: 0 Department: Undefined Salary: $0.0 2. 2-parameter constructor: 4-parameter constructor completed 3-parameter constructor completed 2-parameter constructor completed Name: Alice Age: 30 Department: Undefined Salary: $0.0 3. 3-parameter constructor: 4-parameter constructor completed 3-parameter constructor completed Name: Bob Age: 25 Department: Engineering Salary: $0.0 4. 4-parameter constructor: 4-parameter constructor completed Name: Charlie Age: 35 Department: Sales Salary: $75000.0 5. Copy constructor: 4-parameter constructor completed Copy constructor completed Name: Charlie Age: 35 Department: Sales Salary: $75000.0 6. Invalid constructor call: Error: Age cannot be negative
Best Practices for Constructors
- ✅ Always provide at least one constructor in your classes
- ✅ Use constructor chaining (this()) to avoid code duplication
- ✅ Validate parameters in constructors to ensure object integrity
- ✅ Keep constructors focused on initialization, not complex logic
- ✅ Consider using factory methods for complex object creation
- ✅ Use copy constructors when you need to create object copies
- ✅ Make constructors private for singleton pattern or utility classes
- ✅ Document constructors with Javadoc explaining parameters and behavior