Java | Achieving Immutability using Final keyword

|
| By Webner

Problem: What is the difference between using the final keyword with a primitive versus an object? What is immutability and can final assure that?

Final: Final is a keyword in java which is used to make variable, methods, classes immutable. It means we can’t change their state throughout the process.

1. Final Local Variable: Once we declare a variable as final we can’t change it’s value if it is a local variable. It’s compulsory to assign some values once in a lifetime to these variables before using them otherwise we will get a compilation error. Also, if we try to change the value of final variables we will get compile time error.

For Example: Let’s see a quick example below:

1
Fig 1(Final local variables)

In above example, number is the final local variable. Now if we try to access it without initialization, it will throw following error:

Exception in thread “main” java.lang.Error: Unresolved compilation problem:
The local variable number may not have been initialized

Also if we try to change the value of the variable, the error will be:

Exception in thread “main” java.lang.Error: Unresolved compilation problem:
The final local variable number may already have been assigned

2. Final Instance variable: Instance variables follow the same concept as local variables except that we can initialize the final variables inside constructor method. Final means the value will not be changed after initial assignment. So two instances can have different values for a non-static final variable. One of main reason to make a variable final is clarity. If we are making a variable as final we know it’s never going to change in the process. We can make more changes to the code with final variables with less concern because we know that some variables aren’t going to change. One of the live example is interfaces. The variable declared inside interfaces are always final by default.

For Example: Below is the example which will describe the instance variable as final:

public class InstanceFinal implements Serializable {
    private static final long serialVersionUID = 1 L;
    final private String name;
    final private int rollno;
    public InstanceFinal() {
    super();
    // TODO Auto-generated constructor stub
    }
    public InstanceFinal(String name, int rollno) {
    super();
    this.name = name;
    this.rollno = rollno;
    }
    public static void main(String[] args) {
    InstanceFinal object = new InstanceFinal();
    //InstanceFinal object =new InstanceFinal("Rahul",1);
    // object.setName(“Raj”);
    System.out.println(object.toString());
    }
    @Override
    public String toString() {
    return "InstanceFinal [name=" + name + ", rollno=" + rollno + "]";
    }

    @Override
    public int hashCode() {
    final int prime = 31;
    int result = 1;
    result = prime * result + rollno;
    return result;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        InstanceFinal other = (InstanceFinal) obj;
        if (rollno != other.rollno)
            return false;
        return true;
    }
    public String getName() {
    return name;
    }
    public int getRollno() {
    return rollno;
    }
    // compilation time error
    public void setName(String name) {
    this.name = name;
    }

In above example, there are two instance variables name and rollno. As these are declared as final they will get values once in a lifetime. The final instance variables will be initialized through constructor. In the above example we have added a default constructor and other one is parameterized.

If we try to create the instance of the above class with the help of default constructor, we will get following error:

Exception in thread “main” java.lang.Error: Unresolved compilation problems:

The blank final field name may not have been initialized
The blank final field rollno may not have been initialized

at InstanceFinal.(InstanceFinal.java:11)
at InstanceFinal.main(InstanceFinal.java:24)

An instance variable declared as final never supports setter methods. If you try to set values for final variables using setter method call, you will get error like below :

Exception in thread “main” java.lang.Error: Unresolved compilation problem :
The final field InstanceFinal.name cannot be assigned

at InstanceFinal.setName(InstanceFinal.java:73)
at InstanceFinal.main(InstanceFinal.java:27)

What is immutability and can final assure that?

An immutable object is an object whose state cannot be modified after it has created. Yes, final keyword assures immutability of classes, methods and variables. If you want to make a class immutable then declare all its methods and variables as final. As we know that final variables’ values can’t be changed after initialization and final methods can’t be override. So, derived class is not able to change the behaviour of the parent class at any cost. To make a class immutable, declare all its variables as final and add final keyword to the class declaration so that no other class would be able to override it. One of the example of immutable class is String class. And the best example for final variables are interfaces.

Leave a Reply

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