There are multiple reasons you may want to declare a variable final
, including:
Simplicity - a final variable must be initalised, and cannot be re-assigned. Hence, a section of code frees the reader from having to reason about mutable state or uninitialised variables. The compiler will prevent both. This means that a final variable will also prevent bugs such as accidental re-assignment or accidental use of an uninitialised class member.
Self-documenting - a variable or class member declared final is an explicit signal to the user of the intent that the variable should never be re-assigned.
Thread-safety - a final reference can safely be read without synchronisation. An immutable object (i.e. all member fields are final, and either primitive or references to other immutable objects), can be concurrently accessed without synchronisation.
Compiler required use cases - only effectively final variables can be referred to in try-with-resources expressions, or captured by lambdas. For an overview of the difference beeween final, effectively final, and implicitly final variables, refer to the following this answer.
As an aside, I've noticed that developers with experience using "pure functional" languages (such as F# and Haskell) will tend to favour liberal use of final
. In these languages, all values are "immutable by default". When coming back to Java after working with these languages, I find myself missing the simplicity and freedom afforded by the "immutable by default" approach.
Is it good practice to make all immutable variables final
?
I recommend the following practices, which have served me well as a professional developer over the past decade:
- Class members should be declare
final
by default. Members should be declared non-final only where we explicitly want to make them mutable.
- Variables within methods should be declared final where the value provided (in terms of simlicity and correctness guarantees) outweighs any concerns like clutter. For short methods with few variables, the benefit is mininal. For long methods with many variables, the benefit will be greater.
The use of final method variables also prevents certain coding patterns that are difficult to reason about, due to complex use of mutable state. Mutable state is sometimes necessary, but often isn't.
As an excercise, try declaring all method variable final by default for a day, to get a feel for the patterns and practices needed to support this approach.
There is no universal best practice here. There are tradeoffs to be made between the above benefits and conciseness (some feel that final
keywords add clutter, though I don't tend to agree). The use of final may also depend on compatability with other coding practices (e.g. some people like to use default constructors, and then use setters to populate fields, which I'd argue is not a good practice).
There are many proponents of the "always final
, unless there's a reason not to" approach. There are also many who advocate for using final more sparingly, including Bob Martin in Clean Code. The Google Java Style Guide is notably silent on this question.
I don't agree that liberal use of final
goes against the principles of clean code, which values simplicity and self-documenting code.
Do you use final
modifier for all your immutable variables in your programs?
As discussed above, generally:
- Class members - yes,
final
unless there is a reason not to, for a given class member.
- Method variables - not always, but often for non-trivial methods.