Object Construction & Destruction in Java
In the previous blog we learned about static fields, methods, constants, etc. If you want to learn more about it, visit the blog Static Methods and Variables in Java. In this blog, we will go through object construction and destruction. In the previous blog, we discussed how we can define a constructor and create an object using it. As Object Construction plays a vital role, Java provides a number of ways for writing the constructors.
Constructor Overloading and Method Overloading
Just like OOP, Java also supports overloading. Overloading is when the write more than one constructor or method having the same names for constructors and methods but differ in the return type and no of parameters is called overloading. When there is more than one constructor with the same name but differs in no. of parameters and type of parameters is called constructor overloading. While overloading constructors, the constructors must have different types of parameters and different numbers of parameters, because if we use the same signature for the constructors, the constructor will be confused about which constructor to use and will throw an error. So it is mandatory to give different types of parameters or different no. of parameters to the constructor.
e.g.
In the above example there are two constructors with the same name but having different parameters. The first constructor has 0 parameters and the second constructor has 2 parameters.
e.g.
Output:
Method Overloading follows the same concept as Constructor Overloading, only the difference is it overloads the method. When one or more methods having the same name with different datatypes of parameters and different no. of parameters is called Method Overloading. Methods can be overloaded by using two ways.
- By changing the no of arguments -
e.g.
- By changing the datatype of arguments -
e.g.
It is mandatory to use one the two ways for overloading the method. Because if we use the same signature for the methods then the compiler will get confused which method to execute and will throw an error.
e.g.
Output
Field Initialization with default values
If the fields in the constructor are not set explicitly with the values, then the fields are set automatically with the values as: for numbers it is set as 0, for boolean it is set to false and for reference of object it is set to null. It is not good practice to rely on the default values because sometimes it becomes harder for programmers to understand the code if the values are set to default.
For example, if we consider the example Student which has the fields like name, age, and address. Now suppose if we don’t specify the value and the value will be set to the default as the name will have the value as null, age will have 0, and address will also have a value as null. This is not good practice, because if the coder calls getName() or getAddress() then they will get the values as null which were not expected.
Default Constructors
As we have seen in our previous blogs, we have created a default constructor for creating the object of the class. If there are no constructors used in the class, then the default constructor is called implicitly during object creation. The default constructor sets instance fields to the default values like for a number it is set to 0, for a boolean it sets false as the default value, for objects it sets the value as null, etc.
e.g.
If a class has a constructor and if it doesn’t have default constructor, then the compiler will throw an error because we cannot create an object with the constructors other than default constructor.
e.g.
If we consider the above example then it will throw an error because the default constructor is not created, we only have a constructor with 3 arguments. We cannot use this constructor for creating an object. So it's mandatory to have a default constructor when we define any constructor. Note that we can avoid writing the default constructor only when we don’t have any other constructor. But if the class has even a single constructor then it is mandatory to have the default constructor for creating an instance.
Explicit Field Initialization in Java
By overloading the constructor methods in the call, we can construct many ways to set the initial state of the instance fields in the class. It is a good practice to set the instance fields of the class to meaningful values without caring of the constructor call. In the class definition, we can assign any values to the instance fields.
e.g.
In the above example the assignment is done before the constructor starts its execution. The values initialized to the instance fields are not constant values. E can even initialize the instance fields with the method call.
e.g.
Now here in the example, we have a method assignAtrowelId() in which we have assigned the value of static field i.e. atrowelStaticId to the new variable i.e.atrowelValue and this atrowelValue is returned to the method assignAtrowelId(), which is assigned to the atrowelId with the help of method call.
Best Practices for Parameter Names
When defining a constructor many times developers give the names to the parameters that are meaningless, due to which it becomes a frustrating job for any other developer because meaningless names lead him to go through the entire code for understanding what the parameters name does.
e.g.
In the given example we have defined a constructor with two parameters a and b. Now look at this line we will not understand what the parameter a is used for and what b is used for. For knowing it we have to see the code which is written inside the constructor, so now here we will understand that a is used for name and b is used for address.
In large applications if we give the parameters names that are not meaningful, then the developer will have to read the code, which will waste his time. So this is the drawback of not using the meaningful names to the parameters. In order to eliminate this issue we should follow the best practice of giving meaningful names to the parameters when defined in the constructor. Some developers follow the practice of giving the name to the parameter that describes its functionality.
e.g.
Now in this example we can easily figure out just by seeing the definition, the purpose of the parameter name. Another common practice is to use the same name for the parameters that we use for instance fields. For example, if we will call the parameter atrowelName, then the atrowelName will refer to the parameter and not the instance field. But if we want to access the instance fields then we can do it by using “this” keyword. We will learn “this” keyword in our upcoming blogs.
e.g.
Calling Constructor inside the Constructor
There can be some situations where developers want to call the constructor inside the constructor, then we use this keyword. this keyword refers to the implicit parameters of the method. This keyword has other uses too. For example, if the constructor has the form this(......), then the constructor calls the other constructor that has the same name. For example:
e.g.
Now here when the constructor AtrowelStudent(20) will be called, then AtrowelStudent(int) will call the other constructor i.e. AtrowelStudent(String, int)
Initialization Blocks
We have seen two ways of initializing the data fields
- Assigning a value during the declaration.
- Setting a value in the constructor.
Java supports one more mechanism which is Initialization Block. A class declaration may contain an arbitrary block of code. These blocks are executed when the object of the class is created.
e.g.
In the above example atrowelId is initialized in the object initialization block, regardless of which constructor will be used for creating the object. The initialization block runs first and then the constructor is executed. This mechanism is not mandatory and not common.
Using no of ways for initializing the data fields, makes it quite confusing for the construction process. Now we will see what happens when the constructor is called.
- If the constructor has another constructor inside it, then the constructor calls the inner constructor and that inner constructor gets executed with the provided arguments.
- Else,
- The data fields that are defined in the class are initialized to default values i.e. 0 if it is a number, null if object or false if boolean.
- All the initialization blocks and field initializers that are used in the class are executed in the sequential order i.e. the order in which they occur in the class declaration.
- Execution of the body of constructor
It is always a best practice to organize the initialization code in a manner so that the programmer can easily understand it without having a deep knowledge of the language. In order to initialize the static fields we can either use the static block or can provide an initial value.
e.g.
Suppose if the static field has the complex initialization code then we can use a static initialization block. To define it in the static block we must use the static keyword at the beginning of the block.
e.g.
As the static initialization occurs when the class is first loaded, the value of static fields and instance fields is 0 if the value is in the number, false if it is boolean and null if it is an object. The static fields and instance fields can have other values only when they are set explicitly.s
e.g.
Object Destruction and finalize()
Many times there occurs a situation where the object is no longer needed. In order to remove it or clean up the code, destructor methods are used in C++. Since Java supports garbage collection, manual memory reclamation is not needed, so Java doesn’t support destructors. Many times there may be a situation where an object will use resources other than memory. In this case, it becomes important that the resource be reclaimed and recycled when it is no longer needed. We can use the close() method in order to do the cleanup whenever we have finished using the resource. We can call the close() method whenever we are one with the object.
Note: do not use the finalize() method for cleanup purposes. The purpose of this method was to be called before the garbage collector cleans away an object. But the drawback is we don’t know when this method will get called, so this method is deprecated.