INTRODUCTION
In Java, a constructor is a special type of method that is used to initialize objects. A constructor is called when an object of a class is created. Unlike regular methods, constructors do not have a return type and are named the same as the class they are in.
Constructors allow you to set initial values for object attributes or perform any setup procedures when an object is created.
Key Characteristics of Constructors:
- Initialization: Constructors are primarily used to initialize objects with default or user-defined values.
- No Return Type: Unlike methods, constructors don’t have a return type, not even void.
- Automatically Called: A constructor is automatically invoked when you create an object using the new keyword.
Purpose of Constructors in Java:
Constructors in Java serve several important purposes in object-oriented programming. They are special methods used to initialize objects when they are created. Here are the key purposes and roles of constructors in Java:
Object Initialization | The primary purpose of a constructor is to initialize the object when it is created. It sets the initial state of an object by assigning values to the instance variables of the class. |
Overloading Flexibility | Constructor overloading in Java allows a class to have multiple constructors with different parameter lists. This enables objects to be initialized in various ways, such as with default values, specific values, or by copying other objects. By defining constructors with different parameters, you can provide flexibility in how objects are created based on the available information at the time of instantiation. |
Encapsulation | Constructors play a role in encapsulation by hiding the internal implementation details of how objects are created and initialized. You can control how the fields of an object are set up and ensure that invalid values aren’t assigned. |
Code Reusability | By using constructors, you reduce the need for repetitive code. Instead of manually setting the values of an object’s fields every time you create an object, a constructor allows you to centralize the initialization logic in one place. This makes your code cleaner and easier to maintain. |
Types of Constructors in Java
In Java, constructors are special methods used to initialize objects. There are mainly four types of constructors along with variations that offer more control over object creation.
Default Constructor:
- Automatically provided by Java if no constructor is explicitly defined.
- Initializes object fields with default values (e.g., 0 for numeric types, null for objects).
- If no constructor is defined by the programmer, the compiler provides a default constructor automatically.
Parameterized Constructor:
- Takes arguments to initialize object attributes with specific values during object creation.
- Provides more control over the initialization process.
Syntax of Parameterized Constructor:
class ClassName {
// Parameterized constructor
public ClassName(Type parameter1, Type parameter2, …) {
// Initialization code
}
}
Example
class Car { String color; int year; // Parameterized constructor public Car(String color, int year) { this.color = color; this.year = year; } // Method to display car details public void display() { System.out.println(“Car color: ” + color + “, Year: ” + year); } } public class Main { public static void main(String[] args) { // Creating an object of Car using the constructor Car myCar = new Car(“Red”, 2021); myCar.display(); } } Explanation: In this example, the Car class has a parameterized constructor that initializes the color and year. In main(), we create a Car object and pass values for color and year to the constructor. The display() method shows the car details. |
Output
Car color: Red, Year: 2021 |
No-Argument Constructor (Explicit):
A constructor with no parameters, explicitly defined, to initialize objects with default or custom values.
Syntax of No-Argument Constructor (Explicit):
class ClassName {
// Explicit no-argument constructor
public ClassName() {
// Initialization or setup code (optional)
}
}
Example
class Book { String title; String author; // No-argument constructor (Explicit) public Book() { // Custom initialization (you can also initialize members here) title = “Unknown Title”; author = “Unknown Author”; } // Method to display book details void display() { System.out.println(“Title: ” + title + “, Author: ” + author); } public static void main(String[] args) { // Creating an object using the no-argument constructor Book myBook = new Book(); myBook.display(); } } Explanation : In this example, the Book class has an explicit no-argument constructor that initializes the title and author fields with default values. When the Book object is created using the no-argument constructor, it shows the default values instead of leaving them uninitialized. |
Output
Title: Unknown Title, Author: Unknown Author |
Copy Constructor
A constructor that creates a new object as a copy of an existing object, duplicating the values of the original object.
Syntax of a Copy Constructor
ClassName(ClassName otherObject) {
// Copy the values from the otherObject
}
Example
class Car { String model; int year; // Constructor to initialize a Car object public Car(String model, int year) { this.model = model; this.year = year; } // Copy constructor public Car(Car otherCar) { this.model = otherCar.model; this.year = otherCar.year; } // Method to display car details void display() { System.out.println(“Model: ” + model + “, Year: ” + year); } public static void main(String[] args) { // Creating an object of Car using the parameterized constructor Car car1 = new Car(“Tesla”, 2021); // Creating a new object by copying the values of car1 using the copy constructor Car car2 = new Car(car1); // Displaying details of both car objects car1.display(); car2.display(); } } Explanation: The program uses a parameterized constructor to initialize a Car object with specific model and year values. The copy constructor creates a new Car object (car2) by copying the values from an existing object (car1). The display() method prints the details of both objects, showing identical values since car2 is a copy of car1. |
Output
Model: Tesla, Year: 2021 Model: Tesla, Year: 2021 |
Why we use the constructor in java
In Java, we use constructors to initialize objects. They set the initial values for the object’s attributes when it’s created, ensuring that the object starts in a valid state. Constructors allow for:
- Object Initialization: Setting default or specific values to fields.
- Enforcing Proper Object State: Ensuring objects are properly configured before they are used.
- Simplified Code: Reducing code repetition by centralizing the initialization logic.
Constructor with this Keyword
The this keyword is often used in constructors to refer to the current instance of the class. It can also be used to call another constructor in the same class (constructor chaining).
Example of Using this in Constructor
class Employee { String name; int age; // Constructor with parameters public Employee(String name, int age) { this.name = name; this.age = age; } // Constructor chaining using ‘this’ public Employee(String name) { this(name, 30); // Default age is set to 30 } public void display() { System.out.println(“Name: ” + name + “, Age: ” + age); } public static void main(String[] args) { Employee emp1 = new Employee(“John”, 25); Employee emp2 = new Employee(“Doe”); emp1.display(); emp2.display(); } } |
Constructor Overloading
Just like methods, constructors can also be overloaded in Java. Constructor overloading allows a class to have multiple constructors with different parameter lists. This enables the creation of objects in different ways.
Syntax of Constructor Overloading:
class ClassName {
// Constructor 1
public ClassName() {
// Initialization code (no parameters)
}
// Constructor 2 (overloaded)
public ClassName(Type parameter1) {
// Initialization code using parameter1
}
// Constructor 3 (overloaded)
public ClassName(Type parameter1, Type parameter2) {
// Initialization code using parameter1 and parameter2
}
// More constructors can be added with different parameter types
}
Example
class Car { String model; int year; String color; // Constructor with no parameters public Car() { model = “Unknown”; year = 0; color = “Unknown”; } // Constructor with one parameter public Car(String model) { this.model = model; year = 0; color = “Unknown”; } // Constructor with two parameters public Car(String model, int year) { this.model = model; this.year = year; color = “Unknown”; } // Constructor with three parameters public Car(String model, int year, String color) { this.model = model; this.year = year; this.color = color; } public void displayInfo() { System.out.println(“Model: ” + model); System.out.println(“Year: ” + year); System.out.println(“Color: ” + color); } } public class Main { public static void main(String[] args) { // Creating objects using different constructors Car car1 = new Car(); Car car2 = new Car(“Toyota”); Car car3 = new Car(“Honda”, 2022); Car car4 = new Car(“BMW”, 2021, “Black”); // Displaying the information of each car System.out.println(“Car 1 Info:”); car1.displayInfo(); System.out.println(); System.out.println(“Car 2 Info:”); car2.displayInfo(); System.out.println(); System.out.println(“Car 3 Info:”); car3.displayInfo(); System.out.println(); System.out.println(“Car 4 Info:”); car4.displayInfo(); } } |
Output
Car 1 Info: Model: Unknown Year: 0 Color: Unknown Car 2 Info: Model: Toyota Year: 0 Color: Unknown Car 3 Info: Model: Honda Year: 2022 Color: Unknown Car 4 Info: Model: BMW Year: 2021 Color: Black |
Constructor Overriding
In Java, constructor overriding is a concept that is often misunderstood. While Java allows method overriding, it does not support constructor overriding. Constructors are unique to the class in which they are defined and are not inherited by subclasses, so they cannot be overridden like regular methods.
Why Constructor Overriding Does Not Exist in Java
- Constructors are not inherited: Constructors are not inherited by subclasses and cannot be overridden. Each class has its own constructors that are used only within that class.
- Constructors do not have a return type: Unlike methods, constructors do not have a return type, which is why the concept of overriding doesn’t apply to them.
- Constructor call via super(): In inheritance, the subclass can explicitly call the parent class constructor using super(), ensuring the parent class is initialized before the subclass.
Constructor Chaining
Constructor chaining refers to the practice of calling one constructor from another constructor in the same class or from a superclass. This is useful for avoiding code duplication.
There are two types of constructor chaining in Java:
- Within the same class: Using the this() keyword.
- From the superclass: Using the super() keyword.
Chaining within the same class
class Car { String color; int year; // Constructor with parameters public Car(String color, int year) { this.color = color; this.year = year; } // Constructor with no parameters public Car() { this(“Unknown”, 0); // Calls the parameterized constructor } } |
Chaining with a superclass
When a subclass has a constructor, it can call a constructor from its superclass using the super() keyword.
class Vehicle { String type; public Vehicle(String type) { this.type = type; } } class Car extends Vehicle { String color; public Car(String color) { super(“Car”); // Calls the Vehicle constructor this.color = color; } } |
Access Modifiers in Constructors
In Java, access modifiers control the visibility and accessibility of classes, methods, variables, and constructors. When applied to constructors, access modifiers determine where and how an object of the class can be created.
Public Constructor
A public constructor is accessible from any other class in any package. This is the most common modifier for constructors, especially when you want to allow the creation of objects freely from other parts of the program.
Example
class Car { String model; // Public constructor public Car(String model) { this.model = model; } } public class Main { public static void main(String[] args) { // Object creation using the public constructor Car myCar = new Car(“Tesla”); System.out.println(myCar.model); } } Explanation : In this example, the Car class has a public constructor, allowing the Main class (even in a different package, if necessary) to create an instance of Car. |
Output
Tesla |
Private Constructor
A private constructor is only accessible within the class in which it is defined. It prevents object creation outside of that class, which can be useful in certain design patterns, such as the Singleton pattern or Factory pattern.
Example
class Singleton { private static Singleton instance; // Private constructor private Singleton() { // Initialization code } // Public method to provide access to the single instance public static Singleton getInstance() { if (instance == null) { instance = new Singleton(); } return instance; } } public class Main { public static void main(String[] args) { // The only way to get the instance is through the public method Singleton obj = Singleton.getInstance(); System.out.println(obj); } } Explanation : In this case, the constructor of the Singleton class is marked as private, ensuring that the class cannot be instantiated directly from outside. The getInstance() method provides access to the single instance of the class. |
Output
Singleton@1a2b3c4 |
Protected Constructor
A protected constructor can be accessed within the same package and by subclasses (even if they are in different packages). This is useful when you want to allow subclasses to instantiate the class while preventing direct instantiation from other classes outside of the package.
Example
class Vehicle { String brand; // Protected constructor protected Vehicle(String brand) { this.brand = brand; } } class Car extends Vehicle { // Constructor in subclass public Car(String brand) { super(brand); // Calling protected constructor of the parent class } public void displayInfo() { System.out.println(“Car brand: ” + brand); } public static void main(String[] args) { Car myCar = new Car(“BMW”); myCar.displayInfo(); } } Explanation : In this example, the Vehicle class has a protected constructor, which means it can be called from the Car class (a subclass) even though they are in different packages. However, it cannot be accessed from classes that are neither in the same package nor subclasses. |
Output
Car brand: BMW |
Default Constructor
If no access modifier is provided for a constructor, it has default access, meaning it is accessible only within classes in the same package. This is also called package-private access. It can be used when you want the object creation to be limited to classes within the same package.
Example
class Book { String title; // Default (package-private) constructor Book(String title) { this.title = title; } public void displayInfo() { System.out.println(“Book title: ” + title); } } public class Main { public static void main(String[] args) { // Object creation within the same package is allowed Book myBook = new Book(“Java Programming”); myBook.displayInfo(); } } Explanation : This program defines a Book class with a default (package-private) constructor that sets the book title. The displayInfo() method prints the title. In the Main class, a Book object is created with the title “Java Programming”, and its details are displayed. Since both classes are in the same package, the default constructor is accessible. |
Output
Book title: Java Programming . |
Constructor Accessibility and Inheritance
When dealing with inheritance, it is important to note how access modifiers affect constructors:
- A public constructor in a parent class can be accessed from anywhere, and thus the subclass can call it directly using super().
- A protected constructor can only be called from the subclass (or within the same package).
- A private constructor cannot be accessed or called from a subclass. This is why it is often used in Singleton classes — to restrict object creation to a single instance.
- If a class has a default constructor (package-private), it can be accessed by classes within the same package, but not outside it.
Conclusion
Constructors are fundamental in Java, as they initialize objects and set their initial state. Understanding how constructors work, along with features like constructor overloading and chaining, is key to writing efficient and flexible Java code.