final
is a reserved keyword dedicated to restricting customization to the member/entity it is tagged to. It is a non-access modifier which is applicable to class and its members(variables and methods). With common intention to restrict customization, it behaves differently according to tagged member/entity.
We will look at the use of final
keyword with the followings.
Using final with class prevents it to get inherited by any other class. The reason for making a class final can have two reasons:
final class Parent{
int parVal;
}
class Child extends Parent{
int childVal;
}
public class ClassMain{
public static void main(String args[]){
Child obj = new Child();
}
}
ClassMain.java:5: error: cannot inherit from final Parent
class Child extends Parent{
^
1 error
Using final
with a variable, makes it a constant, un-modifiable after its first assignment. It is important to initialize the final type variable by any of the following ways in order to avoid a compile-time error.
It is a convention to only use uppercase for the name of final variables to be identified easily.
class MyClass{
//Version 1: Initialize right at the time of its declaration
final int FINALVAR1=10;
static final int FINALVAR2; //It is static, so that static block can refer and use it.
final int FINALVAR3;
final int FINALVAR4;
//Version 2: Create a static block and initialize them
static{
FINALVAR2 = 20;
}
//Version 3: Initialize the variable inside every version of constructor
MyClass(int initFinalVar){
FINALVAR3 = initFinalVar;
}
//Version 4: Create an anonymous block/instance initializer block and initialize variables in it
{
FINALVAR4= 40;
}
}
public class ClassMain{
public static void main(String args[]){
MyClass obj = new MyClass(30);
System.out.println("FINALVAR1 = "+obj.FINALVAR1);
System.out.println("FINALVAR2 = "+obj.FINALVAR2);
System.out.println("FINALVAR3 = "+obj.FINALVAR3);
System.out.println("FINALVAR4 = "+obj.FINALVAR4);
}
}
FINALVAR1 = 10 FINALVAR2 = 20 FINALVAR3 = 30 FINALVAR4 = 40
Now let us try changing the values.
class MyClass{
//Version 1: Initialize right at the time of its declaration
final int FINALVAR1=10;
static final int FINALVAR2; //It is static, so that static block can refer and use it.
final int FINALVAR3;
final int FINALVAR4;
//Version 2: Create a static block and initialize them
static{
FINALVAR2 = 20;
}
//Version 3: Initialize the variable inside every version of constructor
MyClass(int initFinalVar){
FINALVAR3 = initFinalVar;
}
//Version 4: Create an anonymous block/instance initializer block and initialize variables in it
{
FINALVAR4= 40;
}
}
public class ClassMain{
public static void main(String args[]){
MyClass obj = new MyClass(30);
System.out.println("(BEFORE)FINALVAR1 = "+obj.FINALVAR1);
System.out.println("(BEFORE)FINALVAR2 = "+obj.FINALVAR2);
System.out.println("(BEFORE)FINALVAR3 = "+obj.FINALVAR3);
System.out.println("(BEFORE)FINALVAR4 = "+obj.FINALVAR4);
obj.FINALVAR1++;
obj.FINALVAR2++;
obj.FINALVAR3++;
obj.FINALVAR4++;
System.out.println("(AFTER)FINALVAR1 = "+obj.FINALVAR1);
System.out.println("(AFTER)FINALVAR2 = "+obj.FINALVAR2);
System.out.println("(AFTER)FINALVAR3 = "+obj.FINALVAR3);
System.out.println("(AFTER)FINALVAR4 = "+obj.FINALVAR4);
}
}
Output:
ClassMain.java:35: error: cannot assign a value to final variable FINALVAR1
obj.FINALVAR1++;
^
ClassMain.java:36: error: cannot assign a value to final variable FINALVAR2
obj.FINALVAR2++;
^
ClassMain.java:37: error: cannot assign a value to final variable FINALVAR3
obj.FINALVAR3++;
^
ClassMain.java:38: error: cannot assign a value to final variable FINALVAR4
obj.FINALVAR4++;
^
4 errors
Using final
with methods, makes it override resistant. After inheriting a parent class, the child class can override the inherited methods. In order to restrict overriding to the inherited method, we use the final
methods.
class Parent{
final void printDetails(){
System.out.println("I am parent version and cannot be overridden ");
}
}
class Child extends Parent{
@Override
void printDetails(){
System.out.println("I am child version and will result in compile error");
}
}
public class ClassMain{
public static void main(String args[]){
Parent obj = new Parent();
obj.printDetails();
obj = new Child();
obj.printDetails();
}
}
ClassMain.java:9: error: printDetails() in Child cannot override printDetails() in Parent void printDetails(){ ^ overridden method is final 1 error
This example illustrates that the final method is inherited but as an override-resistant method
class Parent{
final void printDetails(){
System.out.println("I am parent version and cannot be overridden ");
}
}
class Child extends Parent{
}
public class ClassMain{
public static void main(String args[]){
Parent obj = new Parent();
obj.printDetails();
obj = new Child();
obj.printDetails();
}
}
I am parent version and cannot be overridden I am parent version and cannot be overridden
This was an overview of the final
keyword. We will discuss the Java Abstract classes and methods in the next lecture.