Constructors In Java – Unveiling Object Creation

A constructor in Java is a unique method used in object-oriented programming to initialize objects of a class. It is automatically invoked when an object is created using the new keyword and has the same name as the class.

The main goal of a constructor is to make sure that an object (previously discussed) is correctly initialized and in a valid state before it is used. A valid state denotes that an object is in good and useable condition. In other words, it signifies that all of the crucial information included within the object has been properly configured.

Syntax:

[access modifier] ClassName([parameters]) {
    // Constructor body
    // Initialization code and other statements
}

In the above syntax:

  • [access modifier] specifies the visibility of the constructor, such as public, private, or protected. If no access modifier is specified, it defaults to package-private.
  • ClassName is the name of the class to which the constructor belongs. It must match the class name exactly.
  • parameters represent any input values that the constructor may accept. Multiple parameters are separated by commas.
  • The constructor body contains the initialization code and other statements that execute when the constructor is called.

Let’s take the example of a Car object. For the Car object to be in a valid state, it means that its characteristics, like the make (brand), model, and manufacturing year, have been set to meaningful values that make sense for a car. If any of these characteristics are missing or have incorrect values, the Car object would not be in a valid state.

Example:

public class Car {
    private String make;
    private String model;
    private int year;

    // Constructor with parameters
    public Car(String make, String model, int year) {
        this.make = make;
        this.model = model;
        this.year = year;
    }

    // Default constructor (no parameters)
    public Car() {
        this.make = "Unknown";
        this.model = "Unknown";
        this.year = 0;
    }

    // Other methods and members of the Car class...
}

We have a Car class with two constructors in this example. The first constructor takes three inputs (make, model, and year) and sets the member variables accordingly. The second constructor is a default constructor that assigns default values to the memberJava variables.

Now, let’s create Car objects using these constructors:

public class Main {
    public static void main(String[] args) {
        Car car1 = new Car("Toyota", "Corolla", 2021);
        // Constructor with parameters is called, creating a Car object with the provided values

        Car car2 = new Car();
        // Default constructor is called, creating a Car object with default values

        // Accessing the member variables
        System.out.println("Car 1: " + car1.make + " " + car1.model + " " + car1.year);
        System.out.println("Car 2: " + car2.make + " " + car2.model + " " + car2.year);
    }
}

Output:

Car 1: Toyota Corolla 2021
Car 2: Unknown Unknown 0

In the main method, we create two Car objects: car1 and car2. The first object is created using the constructor with parameters, while the second object is created using the default constructor. 

  • car1 is created using the constructor with parameters. Its make is set to “Toyota”, model to “Corolla”, and year to 2021.
  • car2 is created using the default constructor. Since no specific values are passed, its make and model variables are set to “Unknown”, and the year is set to 0 (default values).

Then, we use System.out.println to print the values of make, model, and year for both car1 and car2. The output shows the values assigned to the member variables for each object.

Now you must be wondering that the same thing can be done using methods inside the class Car, and… you are right. You can do the same thing in the following way:

public class Car {
    private String make;
    private String model;
    private int year;

    // Method to set the car details
    public void setCarDetails(String make, String model, int year) {
        this.make = make;
        this.model = model;
        this.year = year;
    }

    // Method to display car information
    public void displayCarInfo() {
        System.out.println(make + model + year);
    }

    // Other methods and members of the Car class...
}

public class Main {
    public static void main(String[] args) {
        Car car1 = new Car();
        car1.setCarDetails("Toyota", "Corolla", 2021);
       
        Car car2 = new Car();
        car2.setCarDetails("Unknown", "Unknown", 0);

        System.out.print("Car 1: ");
        car1.displayCarInfo();
        System.out.println();

        System.out.print("Car 2: ");
        car2.displayCarInfo();
    }
}

Output:

Car 1: Toyota Corolla 2021
Car 2: Unknown Unknown 0

In this example, we have a Car class with two methods: setCarDetails and displayCarInfo. The setCarDetails method takes the car details as parameters (make, model, and year) and sets the corresponding member variables accordingly.

The displayCarInfo method is responsible for displaying the car information by printing the values of the member variables.

In the main method, we create two Car objects: car1 and car2. After creating the objects, we call the setCarDetails method on each object to set the car details. Then, we call the displayCarInfo method on each object to print the car information.

Question – Why do we need constructors, if we can do the same thing using methods?

Constructors in Java are crucial for object initialization. Unlike methods that perform actions on objects, constructors focus on setting up objects from their creation. They ensure objects start in a valid state, provide standardised initialization, enforce encapsulation, and support inheritance. Constructors simplify the initialization process, allow for default values, and enhance code readability. In short, constructors are essential for proper object setup and initialization in Java.

Difference Between Constructor And Methods In Java

ConstructorsMethods
Used for object initializationUsed for performing actions/calculations
Automatically called when an object is createdExplicitly called by their name
No return type (not even void)Have a return type, e.g., int, String, void
Same name as the classHave their own distinct names
Can be overloaded with different parameter listsCan also be overloaded, but with different names
Can provide default values for member variablesDo not provide default values
Focus on setting up the object’s initial stateFocus on performing specific operations on the object
Enforce encapsulation by initializing private member variablesCan access and modify private variables, but not responsible for object initialization
Inherited from superclass to subclassInherited like any other method, with no special inheritance behavior

Types Of Constructor In Java

In Java, there are three types of constructors: default constructor, parameterized constructor, and copy constructor.

  • Default Constructor: Initializes member variables with default values. No parameters. It sets the object’s initial state to default values.
  • Parameterized Constructor: Accepts parameters to initialize member variables with specific values. This allows objects to be created with different initial states based on the values passed to the constructor.
  • Copy Constructor: Creates a new object by copying values from another object of the same class. You can establish separate instances with identical data by copying values from one object to another, allowing you to operate with them separately.

Let’s deep dive into every type of constructor one by one.

Default constructor

In Java, a Default Constructor is a special constructor that is automatically provided by the Java compiler if no other constructor is explicitly defined in a class. It is called the “default” constructor because it is used when no specific arguments are provided during object creation.

The Default Constructor’s purpose is to assign default values to an object’s member variables. These default values are determined by the variable’s data type. Numeric types, for example, are set to 0, boolean variables are set to false, and reference types (such as objects or strings) are set to null.

Example:

public class Person {
    private String name;
    private int age;

    // Default Constructor
    public Person() {
        name = "Unknown";
        age = 0;
    }

    // Other members and methods...
}

In the example, we have a Person class with a default constructor. The default constructor is defined without any parameters. It initializes the name variable to “Unknown” and the age variable to 0. These are the default values assigned to the member variables when a new Person object is created without explicitly providing any arguments.

The Default Constructor allows you to create objects of the Person class without specifying any values. For instance, if you create a Person object using Person person = new Person();, the name will be “Unknown” and the age will be 0.

Parameterized Constructor

In Java, a Parameterized Constructor is a special type of constructor that allows you to define constructors with one or more parameters. It enables you to initialize the member variables of an object with specific values provided during object creation.

By accepting arguments, the Parameterized Constructor allows flexibility and customization. When you use a parameterized constructor to create an object, you can pass values for the arguments that match the stated types. These values are then used to initialize the member variables.

Example:

public class Person {
    private String name;
    private int age;

    // Parameterized Constructor
    public Person(String personName, int personAge) {
        name = personName;
        age = personAge;
    }

    // Other members and methods...
}

In the example, we have a Person class with a parameterized constructor. The constructor is defined with two parameters: personName of type String and personAge of type int. The constructor assigns the values passed as arguments to the corresponding member variables name and age.

When you create a Person object using the parameterized constructor, such as Person person = new Person(“John”, 25);, the name will be “John” and the age will be 25. 

Now what if you want to declare an object (instance) with different parameters? That’s it, Java got your back. The answer to this issue is Constructor Overloading. 

Constructor Overloading

Constructor Overloading is a feature in Java that allows a class to have multiple constructors with different parameter lists. With constructor overloading, you can define constructors that accept different combinations of parameters, providing flexibility in object creation.

Constructor Overloading enables you to create objects using different initialization options. By having multiple constructors, each accepting different sets of parameters, you can choose the appropriate constructor based on your needs.

Example:

public class Rectangle {
    private int width;
    private int height;

    // Constructor with two parameters
    public Rectangle(int rectWidth, int rectHeight) {
        width = rectWidth;
        height = rectHeight;
    }

    // Constructor with one parameter (Square)
    public Rectangle(int sideLength) {
        width = sideLength;
        height = sideLength;
    }

    // Other members and methods...
}

In the example, we have a Rectangle class with two constructors. The first constructor accepts two parameters rectWidth and rectHeight to set the width and height of the rectangle. The second constructor accepts a single parameter sideLength, assuming that both the width and height of the rectangle are the same (for creating a square).

When you create a Rectangle object, you can choose the appropriate constructor based on your requirements. For example, Rectangle rect1 = new Rectangle(10, 20); creates a rectangle with a width of 10 and a height of 20, while Rectangle rect2 = new Rectangle(15); creates a square with a side length of 15.

Copy Constructor

A Copy Constructor in Java is a particular constructor that takes an argument of the same class and creates a new object that is a duplicate or clone of the original object. It enables you to build a new object with identical member variable values as the original object.

The Copy Constructor is handy when you wish to make independent copies of things while keeping the original object’s state. It assures that modifications made to the cloned item do not have an impact on the original object, and vice versa.

Example:

public class Student {
    private String name;
    private int age;

    // Copy Constructor
    public Student(Student original) {
        name = original.name;
        age = original.age;
    }

    // Other members and methods...
}

In the example, we have a Student class with a copy constructor. The copy constructor takes an object of the Student class as a parameter, typically named original. It assigns the name and age values of the original object to the corresponding member variables of the new object being created.

When you create a new Student object using the copy constructor, such as Student student2 = new Student(student1);, a new student2 object is created as a copy of the student1 object. The name and age values of student1 are copied to student2. Changes made to student2 will not affect student1 and vice versa.

The Copy Constructor allows you to create independent copies of objects. It is useful for working with complex objects that have references to other objects. Note that it performs a shallow copy, copying references but not duplicating the referred objects. For a deep copy, additional logic is needed in the Copy Constructor.

What if, you want to restrict the direct instantiation of a class outside itself? That’s where a special type of constructor comes into play and that is Private Constructor.

Private Constructor 

In Java, a private constructor is a constructor that is declared with the private access modifier. It restricts the instantiation of a class from outside the class itself. A private constructor is often used in creating a singleton class. 

A singleton class is one that only enables one instance (object) of itself to be created throughout the program. It ensures that there is a single point of access to the instance, promoting global access and avoiding the creation of duplicate instances.

Example:

public class ExampleClass {
    private ExampleClass() {
        // Private constructor
    }

    public static ExampleClass createInstance() {
        return new ExampleClass();
    }

    public void doSomething() {
        System.out.println("Doing something...");
    }

    public static void main(String[] args) {
        ExampleClass obj = createInstance();
        obj.doSomething();
    }
}

In this example, the private constructor ExampleClass() is within the same class. A static function createInstance() is used to create a class instance, which internally runs the private constructor. The main method creates an object using the createInstance() method and then calls the doSomething() method.

Constructor Chaining In Java Constructor 

Imagine you are building a fancy robot called “RoboBuddy” that can perform various tasks. Each RoboBuddy has different configurations, such as its color, size, and functionality. To create a RoboBuddy, you need to set these configurations.

Now, constructor chaining is like a series of interconnected assembly lines in a factory. Each assembly line takes care of a specific task, and the output of one assembly line becomes the input for the next.

In Java, constructor chaining allows you to connect multiple constructors together, where one constructor calls another constructor to initialize the object. This helps to avoid code duplication and makes it easier to set different configurations for RoboBuddy without repeating the same code in each constructor.

Example:

public class RoboBuddy {
    private String color;
    private int size;
    private boolean hasFunctions;

    public RoboBuddy() {
        this("Blue"); // Calls the parameterized constructor with the color parameter set to "Blue" by default
    }

    public RoboBuddy(String color) {
        this(color, 10); // Calls the parameterized constructor with the color and size parameters
    }

    public RoboBuddy(String color, int size) {
        this(color, size, true);
      // Calls the parameterized constructor with the color, size, and hasFunctions parameters
    }

    public RoboBuddy(String color, int size, boolean hasFunctions) {
        this.color = color;
        this.size = size;
        this.hasFunctions = hasFunctions;
    }

    // Other methods and functionalities of RoboBuddy...
}

In this example, we have a RoboBuddy class with four constructors, each taking different parameters. The constructor chaining is evident through the use of this() calls.

  • The first constructor RoboBuddy() is a no-argument constructor. It calls the second constructor RoboBuddy(String color) with the color parameter set to “Blue” by default.
  • The second constructor RoboBuddy(String color) calls the third constructor RoboBuddy(String color, int size) with the color and size parameters.
  • The third constructor RoboBuddy(String color, int size) calls the fourth constructor RoboBuddy(String color, int size, boolean hasFunctions) with the color, size, and hasFunctions parameters.
  • The fourth constructor RoboBuddy(String color, int size, boolean hasFunctions) sets the color, size, and hasFunctions values of the RoboBuddy object.

By linking the constructors together through this() calls, we can create a chain where the object is initialized with the desired configurations based on the constructor used.

For example, if we call new RoboBuddy() to create a RoboBuddy object, it will follow the constructor chain and eventually call the fourth constructor with the color set to “Blue” by default, the size set to 10, and hasFunctions set to true.

Constructor chaining simplifies the process of creating objects with different configurations by reusing existing constructors. It provides a more flexible and efficient way to initialize objects in a controlled manner.

Conclusion 

  • Constructors are special methods in Java that are used to initialize objects of a class.
  • Constructors have the same name as the class and do not have a return type.
  • Constructors are called automatically when an object is created using the new keyword.
  • Constructors can be used to set initial values for the member variables of an object.
  • Java provides different types of constructors, such as default constructors, parameterized constructors, and copy constructors.
  • Default constructors are automatically provided by the Java compiler if no other constructor is defined in the class.
  • Parameterized constructors allow you to initialize member variables with specific values provided during object creation.
  • Copy constructors create a new object that is a copy or clone of an existing object, allowing for independent modifications.
  • Private constructors can be used to create singleton classes or restrict object creation from outside the class.
  • Constructors can be chained together, where one constructor calls another constructor to avoid code duplication.

In summary, constructors are essential in Java for object initialization. They provide a way to set initial values and customize object creation. By understanding the different types of constructors and their usage, you can effectively design and initialize objects in your Java programs.

Leave a Reply

Your email address will not be published. Required fields are marked *