What is a constructor?
To understand the constructor, let’s first create an object of a class called Bike
.
public class Bike {
private String color;
public void getColor() {
System.out.println("Color of the bike is: " + color);
}
}
To create an bike object we have called: Bike bike = new Bike();
As you can see, it’s a three step process –
- Declare a reference variable bike
- Create an object of class Bike ⇒ new Bike()
- Link this object to the reference variable using equals operator.
Constructor comes into play at step 2
where we are actually creating the object of Bike class: new Bike()
. It might look like we are calling a method called Bike()
, but that is not true. We are actually calling the Bike constructor. Also we have used the new
keyword as that is the only way to invoke a constructor.
Inside the constructor, we can also set initial values of the instance variable. For example, if we want to ensure that, whenever we create an object of Bike
class, it should have a color
– we can do that initialization inside the constructor
. We will do that in a while.
So we can say, constructor is a sort of special method that is used to create an object and initialize the instance variables of that object.
Rules for constructor
There are couple of rules that you must follow while creating a constructor –
- Constructor name must be the same as its class name.
- A Constructor must have no explicit return type, not even
void
. - A constructor cannot be abstract, static, final, and synchronized.
Where is the constructor in the Bike example?
The answer is, we didn’t write the constructor. But the cool thing is, if you don’t write any constructor, the compiler will write a default constructo
r for you. It looks like below. Default constructor doesn’t accept any argument.
public Bike() {
}
You can write the same constructor by yourself, but if you don’t, the compiler is there for you.
Please remember, if you write your own constructor, the compiler will not add the default constructor for you. So, if you write a constructor that accepts arguments and you need a no argument constructor, you have to write that yourself.
Difference between constructor and method
Let’s understand with an example. In java, it is also allowed to write a method where the method name is the same as the class name as shown below.
public void Bike() {
}
It seems similar to the default constructor. So, how Java will understand which one is the method and which one is the constructor. The answer is – by return type
. A constructor cannot have a return type, but a method must have it. So we can say, there are two main differences between method and constructor –
- A constructor cannot have a return type, but a method must have it.
- Constructor name must be the same as the class name. But the method name may or may not be the same as the class name.
Can we pass arguments to a constructor?
Yes, we can. Let’s use the same Bike
class again and call the getColor()
method.
public class Bike {
private String color;
public void getColor() {
System.out.println("Color of the bike is: " + color);
}
public static void main(String[] args) {
Bike bike = new Bike();
bike.getColor();
}
}
Color of the bike is: null
You can see the value of the color
is missing. So, if you want to ensure that all bikes must have a color
, you should assign the color
from a constructor that accepts arguments.
public class Bike {
private String color;
public Bike(String inputColor) {
color = inputColor;
}
public void getColor() {
System.out.println("Color of the bike is: " + color);
}
public static void main(String[] args) {
Bike bike = new Bike("Red");
bike.getColor();
}
}
Color of the bike is: Red
Types of constructor
There are three types of constructors in Java:
- Default constructor
- No-args (no arguments) constructor
- Parameterized constructor
1. Default constructor: As we have discussed earlier, default constructor is created by the compiler when you don’t write a constructor by yourself. Default constructor doesn’t accept any argument and it doesn’t do anything inside the constructor body.
public class Bike {
private String color;
public Bike() {
}
}
2. No-args constructor: Constructor with no argument is known as a No-Args Constructor. It is similar to the default constructor. However, no-args constructor body can have some code unlike default constructor.
public class Bike {
private String color;
public Bike() {
color = “Red”;
}
}
3. Parameterized constructor: A constructor with arguments is known as Parameterized Constructor.
public class Bike {
private String color;
public Bike(String inputColor) {
color = inputColor;
}
}
Overloaded Constructor
Overloaded constructor means we have multiple constructors in a class with different argument lists.
The whole purpose of the constructor is to create an instance of a class and initialize the instance variable. If we don’t initialize the instance variables, they are assigned with default values.
Sometimes there might be a need to initialize an object in different ways. For example, in Bike
class we can have two constructors –
- One constructor can accept the color value and initialize the color field with that value.
- Another constructor might not accept anything and set a default value (e.g. “Red”) to the color variable.
public class Bike {
private String color;
public Bike(String inputColor) {
color = inputColor;
}
public Bike() {
color = "Red";
}
}
So we have two overloaded constructors: Bike(String inputColor)
& Bike()
.
How to call one overloaded constructor from another?
Let’s first understand why we should do that. In the example above, inside both the overloaded constructor, we are assigning some value to the color variable. This might not seem ugly, but what if we have multiple instance variables? Will you really write duplicate code inside both the constructors? I hope not. Because that will definitely cause maintenance problems. For some reason, if you change something inside one constructor, you have to do a similar change inside the other constructor.
So, whenever possible, the better idea is, put all the constructor code inside the constructor that has the maximum number of parameters and call that constructor from other constructors. To call another constructor, just say this()
and pass the arguments. When we use this()
, it must be the first statement in the constructor.
public class Bike {
private String color;
public Bike() {
this("Red");
}
public Bike(String inputColor) {
color = inputColor;
}
}
A brief overview of inheritance
We’ll discuss inheritance in detail in a dedicated chapter. To understand some concepts of constructor, let’s briefly discuss the concept of inheritance.
Inheritance is the process by which one class inherits functionalities from another class. The purpose behind inheritance is that you can create new classes on top of existing classes so that we can reuse methods and fields of the parent class. Moreover, you can add new methods and fields in your current class also. We call the inheriting class a subclass
or a child class
and the original class is called the parent class
. Inheritance in Java is implemented using extends
keyword. Let’s understand it with an example.
Let’s consider a Camera
class. This class is capable of taking photos.
public class Camera {
public void takePhoto() {
System.out.println("Taking photo ...");
}
}
You can use this Camera class to create an object and call takePhoto()
method to capture a photo. Now let’s consider, you need the zoom feature. Will you really create everything from scratch? No right? Because how to capture the photo is already developed. You just need to add a zoom feature. So, we can extend this Camera class and plug-in only the zoom feature.
public class ZoomCamera extends Camera {
public void takePhotoWithZoom() {
applyZoom();
super.takePhoto();
}
public void applyZoom() {
System.out.print("Applying zoom - ");
}
}
Here to capture photos without zoom, we can use the super class method. Also we have added a new method applyZoom()
to apply zoom before taking a photo with zoom. The super keyword is indicating we are using a method from superclass.
ZoomCamera camera = new ZoomCamera();
camera.takePhoto();
camera.takePhotoWithZoom();
Output:
Taking photo ...
Applying zoom - Taking photo ...
So, a child class is capable of doing everything that the parent class can do and along with that it can do something extra. In other words we can say, when we construct an object of child class, an object will be created in heap memory that will contain both its part and superclass part within itself. So when we call the constructor of a child class, parent class constructor also gets called.
Constructor Chaining
We have understood inheritance briefly in the previous section. As per the example, ZoomCamera extends from Camera. But what about Camera class? Is it extending any class?
The answer is yes. If a class doesn’t extend another class, by default it extends Object
class (provided by java). So essentially, the Object class is always the top class in the inheritance hierarchy. Object class is provided by java. In our example, we can say –
- ZoomCamera extends Camera.
- Camera extends Object.
Also we have discussed, an object not only contains its own part, along with that it contains all superclass parts. To achieve that, when a constructor runs, it immediately calls its superclass constructor and that superclass calls its super class and it goes on until you get the class Object constructor. This process is called constructor chaining.
So, in our example, when we call: ZoomCamera camera = new ZoomCamera()
–
- ZoomCamera() constructor first calls Camera() constructor.
- Camera() constructor then calls Object() constructor.
- As object is the root class, whatever is written inside Object() is executed.
- Then whatever is written inside Camera() gets executed.
- Finally whatever is written inside ZoomCamera is executed.
The reason why superclass constructor is executed first is, as the subclass depends on super class, until the superclass parts of an object are fully formed, subclass parts should not be constructed.
Super keyword
The question is now, how to call a superclass constructor? We can simply use super()
to call super class no-args constructor. The call to super
() must be the first statement in each constructor.
You may think, wait.. I didn’t put anything like super()
inside the Camera or ZoomCamera class. Then how is it working?
The answer is, if you don’t call super()
, the compiler will do it for you. In our example, as you have not added any constructor, the compiler will first add a default constructor for you. Then the compiler will add a no-args superclass constructor call using super()
. So, the Camera and ZoomCamera class will look like –
public class Camera {
public Camera() {
super();
}
}
public class ZoomCamera extends Camera {
public ZoomCamera() {
super();
}
}
Superclass constructor with arguments
Now consider, you have a parameterized constructor in Camera class and ZoomCamera has no constructor.
public class Camera {
private String model;
public Camera(String model) {
this.model = model;
}
}
In line 5, this.model
refers to the model attribute from this class and model
refers to the input model parameter.
public class ZoomCamera extends Camera {
}
You will get a compilation error stating: Implicit super constructor Camera() is undefined for default constructor. Must define an explicit constructor.
Let’s understand the sequence of events –
- First java compiler will check if we have a constructor inside the Camera class. We have one. So the compiler will not add a default constructor. But as the call to super() is missing, the compiler will add a super() call inside the Camera constructor.
- Then the compiler will see, ZoomCamera doesn’t have any constructor. So, the compiler will try to add a default constructor along with super() call.
- Now, the super() means call to super class with no argument constructor. But do we have any no-args constructor inside Camera class? No, right. That is the reason the compiler is throwing the error.
To solve this, we have two options. Either add a no-args constructor in Camera class or explicitly call super() with argument from ZoomCamera class as shown below –
public class ZoomCamera extends Camera {
public ZoomCamera() {
super("Canon");
}
}
Inheritance with overloaded constructor
As we discussed earlier, this() is used to call another overloaded constructor in the same class and if we use this, it must be the first statement in a constructor.
Also we discussed, to call a superclass constructor we use super() and that should be the first statement.
So, if we want to use this() inside a constructor, how are we going to use both this() and super() in the first line of the constructor.
The rule here is, a constructor can have a call to super() or this(), but not both.
You might think, calling super() is mandatory as we need the superclass part inside the subclass. Then when we use this(), are we not calling superclass constructor? The answer is, we have to call superclass constructor and in-fact we are doing that. If you use this() you are essentially calling another constructor in the same class. That other constructor will use super() as the first statement and the superclass constructor will be called.
I hope the concept of constructor is clear by now. If you have any questions, please post your question as a comment. I’ll answer that as soon as I can. Till then, bye bye.