Final Modifier in Java – 6 Important Points To Know

Introduction to Final Modifier in Java:

final is a modifier in Java. The meaning changes from context to context. The final modifier can be used before a class, method, argument, blank field or variable. And its definition changes for each of them. It is available for the below reasons:

  1. Efficiency
  2. Design
  3. Optimization

A filed can be both static and final. It means that it has only one piece of storage that can not be changed. Final variables act as a class variable and they do not take any space on individual objects of the class.

Impact of the final keyword on the variable:

If the final is used before a variable, then the value of that variable will act as a constant and thus, cannot be changed. A final data is a constant in java. Using the final keyword the code conveys the message to the compiler that

  1. It may be a compile-time constant that can not be changed. It applies to parameters, local variables, static and instance as well
  2. A final variable needs to be initialized at the time of declaration. Once the declaration is over, the value can not be altered.
  3. Incase final variables are not initialized, they are called a blank final variable. Blank variables need to be initialized before use.
  4. a reference type final variable can not change its reference value, but the state of the object denotes that it can still be changed.
  5. A final variable of a primitive data type can not change its value once it has been initialized.
  6. A final modifier is only applicable to the local variables or formal parameters.
  7. In general, final static variables are used to define named constants like- Integer.MIN_Values or Integer.MAX_VALUE

In the case of compile-time constant, the compiler may fold the constant value to any of the calculation where it is used. That means the calculation may be performed during compile time instead of run time which eliminates the overhead during runtime. The constant must be primitive and are expressed using the final keyword. A value must be given at the time of definition of such constant.

See also  Class URL in Java

Below is the example of compile-time constant:


final int PIE=3.14;
final double BONUS=.56;

Below is the example of the runtime constant:


final int SLEEPVALUE=(int)(Math.random()*60);
 

abstract class Shape{
    final static int SIZE=20;
    public void display()
    {
        System.out.println("Display method of Shape");
    }
    }
public class Rectangle extends Shape{

public static void main(String []args){
Rectangle obj=new Rectangle();
obj.display();
// obj.SIZE=30;
System.out.println(SIZE);

}

}

The output of the code:
$javac Rectangle.java
$java -Xmx128M -Xms16M Rectangle
Display method of Shape
20
Now if we omit the lines of the redefinition of SIZE


abstract class Shape{
    final static int SIZE=20;
    public void display()
    {
        System.out.println("Display method of Shape");
    }
    }
public class Rectangle extends Shape{

public static void main(String []args){
Rectangle obj=new Rectangle();
obj.display();
obj.SIZE=30;
System.out.println(SIZE);

}

}

The output of the code:
$javac Rectangle.java
Rectangle.java:14: error: cannot assign a value to final variable SIZE
obj.SIZE=30;
^
1 error

If we do not initialize a final variable at the time of declaration, we can do that later by one of the following:

  1. Inside a constructor
  2. Inside an initialize block

Inside a constructor


class ConsTest{
final int x;// blank final
public static void main(String args[]){
ConsTest ct=new Constest();
System.out.println(ct.x);
}
ConsTest(){
x=15;
}
}

Inside an initialization block

A class may contain one or more initialization block. It is a similar concept to the constructor. As soon as the object is created the initialization block executes, before any constructor.


class InitializationTest{
final int y;
public static void main(String args[]){
InitializationTest it=new InitializationTest();
System.out.println(it.y);
}
{
y=20;
}
}

When we can use the initialization block?

We can use the initialization block in the following scenario:

  1. When instance variables are initialized dynamically
  2. to increase code reusability.
  3. If some codes are common across all constructors.

A static final variable

A static final variable can be declared but not initialized initially (blank final variable) but must be initialized before class is used. static final variables are initialized using a static initialization block.

class StaticFinalTest{
final int z;
public static void main(String args[]){
System.out.println(StaticFinalTest.z);
}
static
{
z=15;
}
}

Impact of the final keyword on the Class:

If the final is used before a class, then that class cannot be sub-classed. we generally do not use the final class but for security reason sometimes, we create the class as the final. So nobody can subclass it and can change the methods of how they work. Like-String class. So we can not inherit the class.

putting an entire class is the final means that we don’t want to inherit from this class or allow anyone else to do so. This is done if the class does not need any change. Defining the class as final simply prevents inheritance. So in other words final prevent a class from being further subclasses for security reason. Any such attempt will cause a compile-time error.

See also  Class MissingResourceException in Java

 


class abc{}
final class xyz{
int i=10;
int j=20;
abc x=new abc();
void mno()
{
}
}
// not possible as xyz class is final class
class AnyClass extends xyz{}
public class MyClass{
public static void main(String args[])
{
xyz newClass=new xyz();
newClass.mno();
newClass.i=40;
newClass.j=60;
}
}
 

Impact of the final keyword on the Methods:

If the final is used before a method, then that method cannot be overridden. In this case, nobody can redefine the method. like-println().The same rule applies to final data members irrespective of the class is defined as final. Making a method final serves two important purposes.. they are as follows:

  1. It simply put a lock on the method to prevent any inheriting class from changing its meaning. Mostly we use this as the design phase. It implies that the behaviour of the method is retained. In other words, final methods are not overridden. Any private method of a class is implicitly final as we can not access a private method, hence they can not be overridden. However, adding a final modifier to a private method does not make sense as both do the same thing.
  2.  The second reason is efficiency. It allows the compiler to turn any method call to in line calls. (when the compiler sees a method call mechanism that is to push arguments on the stack, hop over to the method code, execute it, hop back, clean off the stack arguments and deal with the return values,it simply replaces the method call with a copy of the method code that reduces the execution overhead and increases efficiency. However, if the method body is too big, this mechanism may not hold good and may not give improvement)

Defining the class as final simply prevents inheritance. This means that all methods in a final class are implicitly final. (There is no way to override them).

Impact of final on method argument:

Java allows us to make arguments final by declaring them as such in the argument list. The final argument means inside the method, we can not change what the argument handle points to.


class MyClass{
public void doSomething(){}
}
public class FinalArgumentTest{
void withFinal(final MyClass mc)
{
//mc=new MyClass();//not possible as mc is final
mc.doSomething();
}
void withoutFinal(MyClass mc)
{
mc=new MyClass();//possible as mc is not final
mc.doSomething();
}
public static void main(String args[])
{
FinalArgumentTest fat=new FinalArgumentTest();
fat.withFinal(null);
fat.withoutFinal(null);
}
}
 

click here to know more.
We can pass or assign a null handle to an argument without compilation issue for final and non-final arguments.

See also  Switch Case in Java: Quick 5 Minutes Guide

Impact of final on fields:

Java allows us to create final blank fields. They are not given any initialization values but we need to initialize them before we use them. Blank fields provide flexibility like a final filed inside a class can now be different for each object and yet still retains its immutable quality.


public class BlankFinalTest{
final int i=0; //initialized final
final int j; //blank final
final MyClass mc; //blank final handle
//blank final must be initialized in the constructor
BlankFinalTest()
{
    j=1; //initialized the blank field
    mc=new MyClass();
}
BlankFinalTest(int x)
{
    j=x; //initialized the blank field
     mc=new MyClass();
}
     public static void main(String []args){
        BlankFinalTest bft=new BlankFinalTest();
}

}
class MyClass{}

The assignment to final either with an expression at the point of definition of the field or in every constructor.

Impact of final on objects:

When using the final with object handles rather than primitives, the final makes the value constant but with an object handle, the final makes the handle constant. The handle must be initialized to an object at the point of declaration and the handle can never change to any other object.


final object; //handle constant needs to be initialized.
 

The compiler has the same efficiency when we make a class or method final. But as a coder, we don’t know when and how the final class and method will be used. We have to be very careful before making any class or method final. Especially for general-purpose reusable class and methods.

Read more: exception-handling-in-java

Conclusion

  1. All methods of a final class are also final. They will have concrete implementation but can not be overridden.
  2. Type checks are faster for final classes as they are compile-time checked.
  3. Code optimization for final methods is also possible.
  4. It provides greater efficiency in handling non-final methods
  5. During the final method call resolve, the compiler may replace an invocation with the actual body of the method(inlining). This inlining decision is completely dependent on the compiler though.

Share and Enjoy !

Leave a Reply

Your email address will not be published. Required fields are marked *