3

In one Java book I read “In general, it’s a good idea to always declare variables as final, and constant fields as static final, if they don’t need to be reassigned“. I started to follow this advice. But when I started to code, I discovered that almost all my variables are immutable. But using the keyword «final» makes lines longer and as result it is harder to read the code and this goes against the principles of clean code. So here are my questions:

  1. Is it a good practice to make all immutable variables «final»?
  2. Do you use «final» modifier for all your immutable variables in your programs?
  3. If not, when do you use «final» and when do you skip using this keyword?

Here is an example of my program from code coach repository. All variables are final. The same situation almost in all other programs in the repository.

import java.util.Scanner;

public class NoNumerals
{
    public static void main(String[] args) {
        final var input = new Scanner(System.in);
        final var phrase = input.nextLine();
        final String[] numbers = {"zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten"};
        final var updatedPhrase = new StringBuilder();

        for (final var word : phrase.split(" ")) {
            try {
                final int number = Integer.parseInt(word);
                if (number >= 0 && number <= 10) {
                    updatedPhrase.append(numbers[number]);
                } else {
                    updatedPhrase.append(word);
                }
            } catch (NumberFormatException nfe) {
                updatedPhrase.append(word);
            }
            updatedPhrase.append(" ");
        }
        System.out.print(updatedPhrase);
    }
}
Jegors Čemisovs
  • 608
  • 6
  • 14
  • 2
    The practice within Google is not to make a local variable final unless actually necessary (which is rarely, post Java 8's effectively final). The thinking is that it's mostly just noise; and if your method is hard enough to reason about without the final, it's probably too complicated. – Andy Turner Jan 10 '20 at 23:36
  • 1
    1. No. It is pointless, if your variable is effectively `final` the compiler is capable of detecting that. 2. No. I do not. 3. When I need a constant and to ensure that the variable does not unexpectedly change; an immutable variable (like `String`) is not something I would routinely make `final` (expect when it is a **constant**). – Elliott Frisch Jan 10 '20 at 23:37
  • 1
    For variables defined within a method, I do not use the `final` keyword. For class members, I always do – unless that member can or should be changeable at some point. Note that designating something as `final` should not be trusted as preventing changes, especially for non-primitives. For example, you could designate a List as final, then continue adding things to it: `final List x = new ArrayList<>(); x.add("test");` – Kaan Jan 10 '20 at 23:48
  • @kaan Yes, I know this. It is just prevent to reassign x to another list. – Jegors Čemisovs Jan 10 '20 at 23:56

1 Answers1

3

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.
grantn
  • 185
  • 1
  • 8