⏱️ 25 min read • Beginner to Intermediate • Lesson 60
Lesson 60 of 124 of Java Tutorial
You have completed this lesson
Completed on .
You can revise this lesson or continue to the next topic.
The final keyword in Java restricts reassignment, overriding, or inheritance depending on where it is used.
You can apply final to variables, fields, parameters, methods, and classes. However, its exact meaning changes with the declaration. A final reference cannot point to another object, but the object it references may still be mutable.
What Is the final Keyword in Java?
final is a non-access modifier that applies a restriction to a declaration. It does not mean exactly the same thing everywhere: a final variable cannot be assigned again, a final method cannot be overridden, and a final class cannot be extended.
Simple Meaning:final prevents a selected kind of change after the declaration has been completed.
Three Main Uses of final
Declaration
Effect of final
Variable, field, or parameter
Cannot be assigned another value after its permitted initialization.
Instance method
Cannot be overridden by a subclass.
Class
Cannot be extended.
Final Variables
A final variable can be assigned only once. After initialization, another assignment causes a compilation error.
FinalVariableExample.java
Copy Try Download
class FinalVariableExample {
public static void main(String[] args) {
final int passingMarks = 40;
System.out.println(passingMarks);
// passingMarks = 50; // Compilation error
}
}
Output:
40
Explanation
passingMarks is declared as a final int.
Once initialized with 40, it becomes a constant for its scope.
Attempting to reassign it to 50 leads to a compilation error.
A final variable does not have to be initialized on the declaration line, but it must be assigned exactly once before it is used.
Blank Final Variables
A blank final field is declared without an initializer. Every constructor must assign it exactly once before construction finishes.
Student.java
Copy Try Download
class Student {
private final int rollNumber;
private final String name;
Student(int rollNumber, String name) {
this.rollNumber = rollNumber;
this.name = name;
}
void display() {
System.out.println(rollNumber + " - " + name);
}
public static void main(String[] args) {
Student student = new Student(101, "Ayan");
student.display();
}
}
Output:
101 - Ayan
Explanation
rollNumber and name are blank final variables since they aren't initialized at declaration.
They must be assigned a value in the constructor exactly once.
After the constructor completes, their values are locked in for the lifetime of the Student object.
Static Final Constants
A static final field belongs to the class and cannot be reassigned after initialization. Constants normally use uppercase words separated by underscores.
AppConfig.java
Copy Try Download
class AppConfig {
static final int MAX_LOGIN_ATTEMPTS = 3;
static final String APP_NAME = "ProwessApps";
public static void main(String[] args) {
System.out.println(APP_NAME);
System.out.println(MAX_LOGIN_ATTEMPTS);
}
}
Output:
ProwessApps
3
Explanation
static final variables belong to the class rather than instances, acting as global constants.
They are named using uppercase letters with underscores by convention.
They cannot be changed after the class is loaded into memory.
Constant reminder: A public constant becomes part of the API. Expose only values that callers should genuinely depend on.
Final Local Variables
A local variable can be final. It may receive its value later, but only once along every valid execution path.
LocalFinal.java
Copy Try Download
class LocalFinal {
public static void main(String[] args) {
final int result;
if (args.length > 0) {
result = 100;
} else {
result = 0;
}
System.out.println(result);
}
}
Output:
0
Explanation
The local variable result is declared final but not initialized immediately.
The if-else block guarantees it gets assigned exactly once regardless of the condition.
This prevents accidental reassignment later in the method.
Final Parameters
Declaring a method parameter final prevents reassignment of the parameter variable inside that method. It does not automatically make the passed object immutable.
FinalParameter.java
Copy Try Download
class FinalParameter {
static int square(final int number) {
// number = 20; // Compilation error
return number * number;
}
public static void main(String[] args) {
System.out.println(square(5));
}
}
Output:
25
Explanation
The method parameter number is declared final.
Inside the square method, its value (5) cannot be reassigned to anything else.
This is a good practice to prevent accidental modification of incoming arguments.
Final Object References
A final reference cannot be changed to point to another object. However, the referenced object's mutable state may still change.
FinalReference.java
Copy Try Download
class Account {
private double balance;
void deposit(double amount) {
balance += amount;
}
double getBalance() {
return balance;
}
}
class FinalReference {
public static void main(String[] args) {
final Account account = new Account();
account.deposit(500);
System.out.println(account.getBalance());
// account = new Account(); // Compilation error
}
}
Output:
500.0
Explanation
account is a final reference to an Account object.
We cannot make account point to a completely new Account object.
However, we CAN modify the internal state of the object it points to (like calling deposit).
Important:final protects the reference assignment, not the entire state of the referenced object.
Final Arrays and Collections
A final array reference cannot be replaced, but its elements can be changed. The same principle applies to mutable collections.
FinalArray.java
Copy Try Download
import java.util.Arrays;
class FinalArray {
public static void main(String[] args) {
final int[] values = {10, 20, 30};
values[0] = 99;
System.out.println(Arrays.toString(values));
// values = new int[] {1, 2}; // Compilation error
}
}
Output:
[99, 20, 30]
Explanation
Similar to object references, values is a final array reference.
The reference itself cannot be pointed to a new array.
But the individual elements within the array (like values[0]) can be freely modified.
Final Methods
A final instance method is inherited but cannot be overridden. Use it when changing the algorithm in a subclass would violate a required rule or invariant.
Payment.java
Copy Try Download
class Payment {
final void validateAmount(double amount) {
if (amount <= 0) {
throw new IllegalArgumentException(
"Amount must be positive");
}
}
}
class CardPayment extends Payment {
void pay(double amount) {
validateAmount(amount);
System.out.println("Paid ₹" + amount);
}
// void validateAmount(double amount) { } // Error
}
Explanation
validateAmount is declared as a final method in the parent class.
CardPayment inherits this method and can call it freely.
However, if CardPayment tries to override validateAmount, the compiler will throw an error. This guarantees the core validation logic cannot be bypassed or changed.
A final method may still be overloaded because overloading creates a different method signature; final only prevents overriding of that inherited signature.
Final Classes
A final class cannot be extended. This can protect a completed design, prevent subclass-based changes, or support immutability when combined with other design rules.
SecurityToken.java
Copy Try Download
final class SecurityToken {
private final String value;
SecurityToken(String value) {
this.value = value;
}
String getValue() {
return value;
}
}
// class CustomToken extends SecurityToken { } // Error
Explanation
The SecurityToken class is marked as final.
It is impossible for any other class (like CustomToken) to inherit from it.
This is often used for security classes or immutable classes (like java.lang.String) to prevent subclassing that might break their design.
Can a Constructor Be final?
No. Constructors are not inherited and cannot be overridden, so applying final to a constructor would have no valid meaning. Constructors can be overloaded by using different parameter lists.
final vs abstract
Combination
Valid?
Reason
final class + abstract class
No
Abstract requires extension; final prevents extension.
final method + abstract method
No
Abstract requires overriding; final prevents overriding.
Final concrete method in abstract class
Yes
The abstract class can lock selected shared behavior.
Final field in abstract class
Yes
It can be initialized directly or by a constructor.
final vs finally vs finalize()
Term
Meaning
final
A keyword used to restrict reassignment, overriding, or inheritance.
finally
A block associated with exception handling that normally runs after try/catch processing.
finalize()
A deprecated object finalization method that should not be used for resource management.
final and Immutability
Final fields are important in immutable classes, but final alone does not guarantee immutability. Mutable objects must not be exposed directly, constructors must make defensive copies where needed, and mutator methods must be avoided.
StudentRecord.java
Copy Try Download
final class StudentRecord {
private final int rollNumber;
private final String name;
StudentRecord(int rollNumber, String name) {
this.rollNumber = rollNumber;
this.name = name;
}
int getRollNumber() {
return rollNumber;
}
String getName() {
return name;
}
}
Explanation
To make a class fully immutable, we make the class final (so it can't be extended).
All fields (rollNumber, name) are made private final so they can't be changed after creation.
Only getter methods are provided—no setters! This guarantees the object's state will never change.
Effectively Final Variables
A local variable is effectively final when it is assigned once and never reassigned, even if the final keyword is omitted. Lambdas and local or anonymous classes can capture final or effectively final local variables.
The variable prefix is never explicitly declared as final.
Because its value is never changed after initialization, Java considers it "effectively final".
This allows lambdas (like task) and anonymous inner classes to safely capture and use it.
Important final Keyword Rules
A final variable can be assigned only once.
A blank final instance field must be initialized by every constructor.
A blank static final field must be initialized at declaration or in a static initializer.
A final reference cannot be reassigned, but its mutable object may change.
A final method cannot be overridden but can be inherited and overloaded.
A final class cannot be extended.
A constructor cannot be final.
A class or method cannot be both abstract and final.
Final local variables and parameters cannot be reassigned.
Captured local variables must be final or effectively final.
Best Practices
Use final fields for values that belong to an object's permanent initialized state.
Use static final for genuine class-level constants.
Name constants with uppercase words separated by underscores.
Use final classes or methods only when preventing extension is part of the design.
Do not assume a final collection or reference is immutable.
Prefer immutable objects and defensive copies when state must not change.
Avoid using final everywhere when it adds noise without communicating a useful guarantee.
Tricky Cases
1. Can a final variable be initialized later?
Yes, provided Java can prove that it is assigned exactly once before use.
2. Can a final reference modify its object?
Yes, when the object is mutable. Only reference reassignment is prohibited.
3. Can a final method be overloaded?
Yes. Overloading creates a method with a different parameter list; overriding the inherited final signature is prohibited.
4. Can a final class implement an interface?
Yes. Final prevents subclasses; it does not prevent the class from implementing interfaces.
5. Can a final class contain non-final methods?
Yes. They cannot be overridden because the class itself cannot be extended.
6. Is final the same as const?
No. Java reserves const but does not use it. The final keyword controls assignment or inheritance-related changes.
7. Does final make a program thread-safe?
No. Final fields have useful initialization guarantees, but mutable shared state still requires an appropriate thread-safety design.
Common Mistakes
Trying to reassign a final variable or reference.
Assuming a final object reference makes the object immutable.
Leaving a blank final field uninitialized in one constructor.
Trying to override a final method.
Trying to extend a final class.
Declaring a class or method both abstract and final.
Trying to declare a constructor final.
Confusing final, finally, and finalize().
Summary:
A final variable cannot be assigned again after initialization.
A final method cannot be overridden.
A final class cannot be extended.
Blank final fields must be initialized exactly once.
Static final fields are commonly used for constants.
A final reference does not make a mutable object immutable.
Constructors cannot be final.
Abstract and final cannot be combined on the same class or method.
Lambdas can capture final or effectively final local variables.
Interview Questions ⭐
The final keyword applies a restriction to a declaration. A final variable cannot be assigned again after initialization, a final method cannot be overridden, and a final class cannot be extended.
A final variable can be assigned exactly once. Any later attempt to assign another value causes a compilation error.
Yes. A final variable may be declared without an initializer, but Java must be able to prove that it is assigned exactly once before it is used.
A blank final variable is declared without an initial value and is assigned exactly once later, such as in a constructor or initializer.
A blank final instance field must be assigned by every constructor, or by an instance initializer that runs before the constructor completes.
A blank static final field must be initialized at its declaration or in a static initializer.
A static final variable belongs to the class and cannot be reassigned after initialization. It is commonly used for class-level constants.
Java constants are conventionally written in uppercase letters with words separated by underscores, such as MAX_LOGIN_ATTEMPTS.
No. After a final local variable receives its value, it cannot be assigned again.
A final parameter cannot be reassigned inside the method. If it refers to a mutable object, the object's state may still change.
A final object reference cannot be changed to refer to another object after initialization.
No. A final reference prevents reference reassignment, but the referenced object may still be modified if it is mutable.
Yes. The array reference cannot be reassigned, but individual array elements can still be modified.
Yes, if the collection itself is mutable. The final modifier prevents assigning a different collection to the variable; it does not prevent add, remove, or update operations.
A final instance method is inherited by subclasses but cannot be overridden.
Yes. Final prevents overriding of the inherited signature, but methods with different parameter lists may still overload the method name.
Yes. A static method may be declared final, although static methods are hidden rather than overridden.
A final class cannot be extended by another class.
Yes. Final prevents the class from being extended; it does not prevent the class from implementing interfaces.
Yes. A final class may contain non-final methods, but no subclass can override them because the class cannot be extended.
No. Constructors are not inherited or overridden, so declaring a constructor final is not permitted.
No. An abstract class must be extended to provide or use its incomplete behavior, while final prevents extension.
No. An abstract method requires a subclass implementation, while final prevents overriding.
Yes. An abstract class may contain concrete final methods whose shared implementation subclasses cannot override.
No. Immutability also requires controlled construction, no mutating operations, and defensive handling of mutable referenced objects.
An effectively final variable is a local variable assigned once and never reassigned, even though the final keyword is not written.
Java requires local variables captured by lambdas, local classes, or anonymous classes to be final or effectively final so their captured values remain stable.
Final is a modifier that restricts assignment, overriding, or inheritance. Finally is a block used with exception handling that normally executes after try and catch processing.
Final is a Java keyword. finalize() is a deprecated Object method related to garbage-collection finalization and should not be used for resource management.
No. Java reserves the const keyword but does not use it. Java uses final to restrict reassignment and inheritance-related changes.
No. Final fields provide useful initialization guarantees, but mutable shared state still requires an appropriate thread-safety design.
Use final when preventing reassignment, overriding, or inheritance communicates an intentional and useful design guarantee.
Discussion
Ask questions, share suggestions, or discuss this lesson.