How does the final keyword in Java work? (I can still modify an object.)
Master System Design with Codemia
Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.
The final keyword in Java is a fundamental concept used to restrict the user. It can be applied to variables, methods, and classes. Despite its outward simplicity, understanding how the final keyword works, particularly in the context of object modification, is essential for Java developers. This article explores the use and functionality of the final keyword, providing insights into its implications in various contexts.
Understanding final with Variables
When the final keyword is used with a variable, it effectively makes that variable a constant. This means that once a final variable has been initialized, its value cannot be changed. However, it's crucial to distinguish between primitive and reference variables.
- Primitive variables: For primitives,
finalensures the value stays constant. For example, afinal int x = 100;meansxwill always be 100. - Reference variables: For objects,
finalmakes the reference constant, not the object itself. For instance, considerfinal List<String> myList = new ArrayList<>();. Here,myListwill always point to the sameArrayListobject, but you can add, remove, or alter objects withinmyList.
Final and Methods
When applied to methods, the final keyword prevents method overriding. This is particularly useful when you want to keep the implementation of a method the same in all extending classes to maintain a specific behavior or protocol. For example, if you define a method as final in a superclass, it cannot be overridden by any subclasses, thus preserving the intended functionality across the hierarchy.
Final and Classes
A class defined as final cannot be subclassed. This is often done to maintain the integrity of the class design, especially in cases where modifications to the base behavior could compromise security or consistency. For example, many of the wrapper classes in Java's standard libraries, such as java.lang.Integer and java.lang.String, are final.
Modifying Objects Through Final References
While final ensures that the reference to an object cannot change, it does not prevent internal modifications to the object itself. This characteristic often leads to confusion among developers who might expect complete immutability from a final object.
Example:
In the example above, the names reference is final and cannot be pointed to another object, but the content within the list can freely change.
Practical Implications and Best Practices
Understandably, the correct use of final can lead to better-designed and more maintainable codebase, allowing programmers to enforce immutability of references, protect method behaviors, and ensure class hierarchies remain unaltered. It also provides slight performance optimization, especially for method calls, as it enables method invocation bypassing dynamic dispatch.
Summary Table
| Aspect | Description | Example |
| Variable | Makes the variable's value (or reference) unchangeable | final int x = 10; |
| Method | Prevents the method from being overridden in subclasses | public final void myMethod() |
| Class | Prevents the class from being subclassed | public final class MyFinalClass |
| Objects | Reference is fixed but the object's state can still be modified | final List<String> myList |
Conclusion
Understanding the final keyword is crucial for both novice and experienced Java developers. It ensures that your Java applications have the necessary immutability, security, or behavior preservation as intended. Use it thoughtfully and understand its implications fully to harness its benefits while avoiding common pitfalls, such as unintentional object mutability.

