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.