Sunday, June 13, 2021

Java Tutorial: The final Keyword

Chapters

The final Keyword

The final keyword can be used in a variable, method and class. The final keyword affects variable, method and class differently.

Using final Keyword In Variables

When we use final keyword in a variable, the value of the variable can't be changed. We call these variables as constants. If the value of a variable is an object reference then the state of the object of the reference can be changed but the reference that is assigned with the variable can't be changed. This property is called non-transitivity.

arrays and collections have this property because arrays and collections are objects. Constant variables require less resources than regular variables. Thus, constants may improve the performance of our program.

Let's create an example to demonstrate final variables.
public class SampleClass{
  //blank final instance variable
  //this variable needs to
  //be instantiated in an
  //initializer block or
  //a constructor
  final String NAME;
  
  //final instance variable
  static final int ONES = 5;
  
  //final instance variable
  //with object reference
  final StringBuilder STR_BUILD = 
                  new StringBuilder("abcd");
  
  //blank final static variable
  //this variable needs to be
  //instantiated in a static
  //block
  //
  //Sometimes, it's convenient to make your
  //final variable static to prevent
  //it from having duplicates
  //everytime we create a class
  //object where the final variable
  //resides
  static final double DECIMAL;
  
  //final static variable
  final static int TENS = 37;
  
  SampleClass(){
    //initialize blank final
    //in a constructor or
    //initializer block
    NAME = "SampleClass";
    
    //error: once blank final is 
    //initialized, we can't
    //change its value anymore
    //NAME = "ClassSample";
  }
  
  static{
    //initialize static blank final
    //in a static block
    DECIMAL = 10.5;
    
    //error: once blank final is 
    //initialized, we can't
    //change its value anymore
    //DECIMAL = 11;
  }
  
  public static void main(String[]args){
    //final local variable
    final int NUM = 1;
    
    //error. can't change num value because
    //it's final
    //NUM = 5;
    
    SampleClass sc = new SampleClass();
    System.out.println(sc.NAME);
    System.out.println(sc.ONES);
    System.out.println(sc.TENS);
    System.out.println(sc.DECIMAL);
    System.out.println();
    
    System.out.println(sc.STR_BUILD.toString());
    System.out.println("Add String...");
    
    //change object state
    sc.STR_BUILD.append("efgh");
    
    //error: reference assigned to builder variable
    //can't be changed
    //sc.STR_BUILD = new StringBuilder("abcdefgh");
    
    System.out.println(sc.STR_BUILD.toString());
  }
}
There are lots of interesting things going on in the example. We see that once a final variable has been initialized, its value can't be changed. If the variable is a reference type variable, the properties of the object referenced by the reference can be changed but the reference that the variable holds can't be changed.

Now, let's talk about blank final variable. This variable can be declared without a value. However, it's required to be initialized in an initializer block or constructor if the variable is non-static, if it's static then it's required to be initialized in a static block.

Using final Keyword In Classes

When final keyword is used in classes, those classes can't be extended or in other words, they can't have child classes.
Note: final keyword doesn't work with abstract classes.
public class SampleClass{

  public static void main(String[]args){
  }
}

final class ClassA{
  static String name = "ClassA";

}

//error: Class can't extend ClassA
class ClassB extends ClassA{
  String name = "ClassB";
}
Using final Keyword In Methods

When final keyword is used in methods, those methods can't be overriden.
public class SampleClass{

  public static void main(String[]args){
  }
}

class ClassA{
  static String name = "ClassA";
  
  //final method
  public final void displayName(){
    System.out.println(name);
  }
  
  //This syntax is legal but final keyword
  //here is redundant since static methods
  //can't be overriden already
  /*
  public final static void displayName(){
    System.out.println(name);
  }
  */
  
}

class ClassB extends ClassA{
  static String name = "ClassB";
  
  //error: can't override final
  //method
  /*
  @Override
  public final void displayName(){
    System.out.println(name);
  }
  */
  
  //error: can't override static method
  /*
  @Override
  final static public void displayName(){
    System.out.println(name);
  }
  */
  
  public void displayParentName(){
    super.displayName();
  }
}
In the above example, we see that displayName() in ClassA can't be overriden. We also see that adding final keyword in a static method is redundant since static methods can't be overriden already.

Another interesting thing is this syntax:
public final static void displayName()
In this syntax we have three modifiers: public access modifier, static and final. Some modifiers can be arranged in any order. These three modifiers can be placed in any order
Example
static public final void displayName(){}

Using final Keyword In Method/Constructor Parameter

When final keyword is used in Method/Constructor Parameter, the value of the parameter can't be changed in the method/constructor block. Otherwise, a compilation error will be thrown.
public class SampleClass{
  
  static void method(final String str){
    String myString = str;
    
    //Uncomment this code below
    //and you will encounter a compilation
    //error
    //str = "This is an error";
  }
  
  public static void main(String[] args){
  
  }
}

No comments:

Post a Comment