Constructor In JAVA

Constructor

Constructors are used to initialize the object. Constructors have the same name as the class name and do not have a return type. We can use the access modifiers with a constructor. Access modifiers define the visibility of constructors to outer classes. Public, private, default, and protected are the access modifiers. A constructor can not be abstract, static, final, native, or synchronized.

Declare the constructor.

public class Employee {
    private int id;
    private String name;

  // decalring of constructor
    public Employee() {
    }
}

There are three types of constructors.

  • Default
  • Parametrized
  • Non-argument

Default constructor

When the user cannot define any constructor in a class, the compiler creates the constructor for us.

Parametrized

When we create and pass the parameters in the constructor it is called the parameterized constructor. In this type of constructor when we call the object we need to pass the parameters at the time of initializing the object. For example,

public class Employee {

   int empId;  
   String empName;  

   //parameterized constructor with two parameters
   Employee(int id, String name){  
       this.empId = id;  
       this.empName = name;  
   }  
   void info(){
        System.out.println("Id: "+empId+" Name: "+empName);
   }  

   public static void main(String args[]){  
    Employee obj1 = new Employee(1,"John");  
    Employee obj2 = new Employee(9,"Mariam");  
    obj1.info();  
    obj2.info();  
   }  
}

Non-argument

When the user implements the constructor without arguments it is called the non-arg constructor. The constructor has the body, but it does not contain any parameters. For example,

class Demo
{
     public Demo()
     {
         System.out.println("This is a no-argument constructor");
     }
     public static void main(String args[]) {
         new Demo();
     }
}

Constructor Chaining

Constructor chaining means calling another constructor in the constructor.

There are two ways we call them in the constructor.

  • Using this keyword.
  • Using super keyword.

This keyword

When we call the constructor within the same class this keyword is used. For example,

public class Student {
    private final String firstName;
    private final String middleName;
    private final String lastName;
    private final int age;

    //getters, setters
}

Every student has the firstName and lastName. But the middle name is optional. Therefore, We are creating the two constructors. The first constructor accepts all the attributes. The second omits the middle name.

public Student(String firstName, String middleName, String lastName, int age) {
    this.firstName = firstName;
    this.middleName = middleName;
    this.lastName = lastName;
    this.age = age;

// First constrcutor
}
public Student(String firstName, String lastName, int age) {
    this(firstName, null, lastName, age);

//Second Constructor
}

The constructor can be placed anywhere in the class. It never gives an error and works the same way.

Super keyword

When we call the constructor from the parent class super keyword is used.
For example,

Customer class that extends the Person Class

public class Person {
    private final String firstName;
    private final String middleName;
    private final String lastName;
    private final int age;

public Person(String firstName, String middleName, String lastName, int age) {
    this.firstName = firstName;
    this.middleName = middleName;
    this.lastName = lastName;
    this.age = age;
}

public Person(String firstName, String lastName, int age) {
    this(firstName, null, lastName, age);
}
}


public class Customer extends Person {
    private final String loyaltyCardId;

   //getters
}

It contains an extra attribute. Now, let's create two constructors in a similar way as in the Person class:

public Customer(String firstName, String lastName, int age, String loyaltyCardId) {
    this(firstName, null, lastName, age, loyaltyCardId);
}

public Customer(String firstName, String middleName, String lastName, int age, String loyaltyCardId) {
    super(firstName, middleName, lastName, age);
    this.loyaltyCardId = loyaltyCardId;
}

The first constructor uses the this() keyword to chain to the second constructor, which accepts all required and optional attributes. Here, we use the super() keyword for the first time.

Its behavior is very similar to the this() keyword. super() chains to the corresponding constructor in the parent class, whereas this() chains to the constructor in the same class.

The benefit of using constructor chaining is there is less duplicate code and makes code more readable. The drawback of constructor chaining is it’s exposing more ways of constructing an object.

Java Copy Constructor

A constructor that creates an object using another object of the same Java class is called a copy constructor. Copy constructors in Java are not inheritable by subclasses.

That's helpful when we want to copy a complex object that has several fields, or when we want to make a deep copy of an existing object.

First, we declare the constructor that takes an object of the same type as a parameter

public class Employee {
    private int id;
    private String name;

    public Employee(Employee employee) {
    }
}

Then, we copy each field of the input object into the new instance:

public class Employee {
    private int id;
    private String name;

    public Employee(Employee employee) {
        this.id = employee.id;
        this.name = employee.name;
    }
}

What we have here is a shallow copy, which is fine since all of our fields – an int and a String in this case – are either primitive types or immutable types.

If the Java class has mutable fields, then we can instead make a deep copy inside its copy constructor. With a deep copy, the newly created object is independent of the original one because we create a distinct copy of each mutable object:

public class Employee {
    private int id;
    private String name;
    private Date startDate;

    public Employee(Employee employee) {
        this.id = employee.id;
        this.name = employee.name;
        this.startDate = new Date(employee.startDate.getTime());
    }
}

Why does the constructor not have a return type?

When the object is created using a command like

Rectangle rectOne = new Rectangle()

In this command, the rectOne is the variable name, and the data type is the Rectangle new is used to create/initialize the object followed by the constructor. It picks the name from the constructor and allocates memory then gives the name to the new operator that’s the reason the constructor name is the same as the class name.

After allocating the memory, the new operator passes the reference id of the newly created object to the constructor Rectangle() as an argument. Now from the last line of constructor, the constructor returns this reference id to variable rectOne which is of class type something like “return this;” and that is the reason Constructor doesn't have a return type since it's already returning something.

Thanks for reading.

Happy to connect on Twitter and Linkedin