Java final Keyword With Examples

Java final keyword

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.

  • Class
  • Variables
  • Methods

final keyword with class

Using final with class prevents it to get inherited by any other class. The reason for making a class final can have two reasons:

  • Restrict inheritance.  Once declared final, a class cannot be extended.
  • Create an Immutable class. It means that once the object is created, it cannot be changed. It is used in a concurrent environment to avoid any change in the object in synchronized blocks.

Example:

 final class Parent{    int parVal; } class Child extends Parent{     int childVal; } public class ClassMain{     public static void main(String args[]){         Child obj = new Child();     } }

Output:

 ClassMain.java:5: error: cannot inherit from final Parent class Child extends Parent{                     ^ 1 error

final keyword with variables

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.

  1. Initialize right at the time of its declaration.
  2. Create a static block and initialize them.
  3. Initialize the variable inside every version of the constructor.
  4. Create an anonymous block/instance initializer block and initialize variables in it.

It is a convention to only use uppercase for the name of final variables to be identified easily.

Example:

 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);     } }

Output:

 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

final keyword with methods

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.

Example:

 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();     } }

Output:

 ClassMain.java:9: error: printDetails() in Child cannot override printDetails() in Parent void printDetails(){   ^ overridden method is final 1 error 

Example 2:

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();     } }

Output:

 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.

×