The final keyword in Java is a non-access specifier. We can apply it to a variable, method or a class. In this tutorial, we’ll learn its usage in each of these contexts.
The variables declared as final are nothing but constants i.e. any attempt to reassign a value to those variables will fail to compile.
The value of a final variable cannot be changed once it is initialized.
Let’s look at some code to understand it better:
class MyCar { final int wheels = 4; static final String color = "Red"; public static void main(String args[]) { final int driverSeat = 1; MyCar obj = new MyCar(); obj.performOperation(driverSeat); obj.performOtherOperation(driverSeat); driverSeat = 2; //fails to compile color = "Blue"; //fails to compile } public void performOperation(final int driverSeat) { System.out.println(driverSeat); driverSeat = 2; //fails to compile } public void performOtherOperation(int driverSeat) { driverSeat = 2; /*allowed, driverSeat here is non-final and Java is pass-by-value */ wheels = 5; //fails to compile } }
There’re some noteworthy takeaways from the above code snippet:
Also on taking a closer look, we can easily draw that we can easily re-assign a value for the driverSeatĀ variable in performOtherOperation() method. It is despite the fact that we passed its value from our main() method which declared its driverSeat variable to be final. This is so because Java is Pass-By-Value.
Any non-static final variable which isn’t assigned a value at the time of its declaration is referred to as a blank final variable. We must initialize its value in either a constructor or an instance initializer, otherwise our code will fail to compile.
class Car { final int wheels; Student(int wheels) { this.wheels = wheels; } public static void main(String args[]) { Car car = new Car(4); System.out.println(car.wheels); } }
Just like any other final variable, once initialized we can’t re-assign it a value.
It’s also possible for us to leave a static final variable uninitialized at the time of its declaration. In such a case, we must assign it a value in the static initializer block, otherwise, our code will fail to compile.
class Car { static final int wheels; static { wheels = 4; } public static void main(String args[]) { System.out.println(wheels); } }
A final method can never be overridden. It simply means that the child class can’t override the final method of its parent class even if it fulfills all other overriding rules.
Let’s look at some code:
class Car { public final void drive() { System.out.println("Driving a car.."); } } class Skoda extends Car { public void drive() { // won't compile System.out.println("Driving Skoda.."); } }
Clearly, the above code won’t compile as the drive() is a final method and we can’t override it in any of its subclasses.
When we mark our Java class as final, it can’t be extended or subclassed.
final class Skoda { int modelNumber; ... } class Octavia extends Skoda { //won't compile ... }
Since we have marked Skoda to be final, it can’t have any subclasses.
We have many final classes like String, StringBuilder, LocalDate etc in our Java library. It prevents any changes or modifications to its actual behavior as it could have severe impacts.
In this tutorial, we covered in-depth about the final keyword in Java. The final keyword in Java can be applied to a variable, method or a class. Let’s quickly sum up our key learnings:
Apart from that, we have also learned about blank final variables and uninitialized static final variables.