136

While I understand what the final keyword is used for in the context of classes and methods as well as the intent of its use for in regards to variables; however, the project I just started working on seems to have an excessive number of them and I'm curious as to the logic behind it.

The following snippet of code is just a short example as I don't see much point in the final keyword for the key and value variables:

private <K, V> Collection<V> getValuesForKeys(
    final Map<K, V> map, final Collection<K> keys) 
{
    final Collection<V> values = new ArrayList<V>(keys.size());
    for (final K key : keys) {
        final V value = map.get(key);
        if (value != null) {
            values.add(value);
        }
    }
    return values;
}

I have been doing a bit of reading the usage through articles I have found via Google; however, does the pattern really do things such as help the compiler optimize the code?

rjzii
  • 11,304

4 Answers4

151

There are many references suggesting a liberal use of final. The Java Language Specification even has a section on final variables. Various rules in static analysis tools also support this - PMD even has a number of rules to detect when final can be used. The pages that I linked to provide a number of points as to what final does and why you should use it liberally.

For me, the liberal use of final accomplished two things in most code, and these are probably the things that drove the author of your code sample to use it:

  1. It makes the intent of the code much more clear, and leads to self-documenting code. Using final prevents the value of a primitive object from changing or a new object being made and overwriting an existing object. If there's no need to change the value of a variable and someone does, the IDE and/or compiler will provide a warning. The developer must either fix the problem or explicitly remove the final modifier from the variable. Either way, thought is necessary to ensure the intended outcome is achieved.

  2. Depending on your code, it serves as a hint for the compiler to potenitally enable optimizations. This has nothing to do with compile time, but what the compiler can do during compilation. It's also not guaranteed to do anything. However, signaling the compiler that the value of this variable or the object referred to by this variable will never change could potentially allow for performance optimizations.

There are other advantages as well, related to concurrency. When applied at a class or method level, having to do with ensuring what can be overridden or inherited. However, these are beyond the scope of your code sample. Again, the articles I linked to go far more in-depth into how you can apply final.

The only way to be sure why the author of the code decided to use final is to find the author and ask for yourself.

Thomas Owens
  • 85,641
  • 18
  • 207
  • 307
50

The principle benefits of "final" in my mind are two-fold:

  • Final variables are "safer" than non-final variables, because once they are bound there is never a question about what their current state is.
  • Because of the above, making a variable final relieves the programmer of excess mental juggling - he/she doesn't have to scan through the code to see if the variable has changed. This happy state-of-affairs will be familiar to anyone who has spent any time in a functional-language setting.

As for this specific example, it may be that the programmer picked up the "final" habit and just applies the "final" keyword everywhere as a matter of course. (I am skeptical of the notion that the final keyword would help the compiler when talking about individual assignments — surely it doesn't need the help to determine only one assignment took place?)

I'm of the opinion that Java got it backwards — there should be no "final" keyword for variables, everything should be "final" by default, and if you want a mutable variable you should have to add a keyword for that ("var" or some such). (As another commenter mentioned, scala has two keywords — "val" and "var" for final and non-final variables, respectively - I'll take it).

Chuck
  • 103
19

In Java the only place to my knowledge where the final keyword is required is to make a variable reliably available to an anonymous class (since the compiler does some trickery under the covers requiring that this value cannot change).

It is - to my knowledge - a myth that the final keyword allows the Java compiler to optimize code, as all optimizations that matter happen in the JIT part of the runtime.

It is therefore a matter of taste. There is, however, one very significant benefit for using lots of finals, namely to make the code easier to read for future maintainers.

Marking a variable as final tells the reader that this variable never, ever changes when assigned. This is very important when reading code as you know when you need to know the value of the variable that it is the same as in the initial assignment and do not have to mentally parse all the code in between to see if the variable is assigned again with something else.

Also if you see that a variable is not marked with final you know that it will be changed further on! This is an extremely important piece of information that can be conveyed to the reader simply by having five characters missing.

Anything that can help the maintainer do his/her job faster and more reliably mean that the application is cheaper to maintain! In other words, final saves real money.

Note: Eclipse has a "source clean-up" option which can insert finals where possible. This might be helpful both for writing new code, and for maintaining old (insert finals, if some are missing the variable is changed after initial assignment). My gut feeling is that this is what the original author discovered and decided to use.

The subject is discussed further at https://stackoverflow.com/q/316352/53897

9

I think the answer to this is simpler than others suggest. It's not about intent, or design. A good while ago, it was true that adding final in some places (particularly, for methods and classes) allowed the JVM to optimise more aggressively. As a result, some people went berserk and put final literally everywhere to try and get their code to go faster.

I should add that it's not the compiler, but the JVM which does the optimisation. Furthermore, I doubt putting final on a local variable would ever have made any difference to performance.

Finally, using final probably wouldn't make much difference these days as JVM optimisations have advanced somewhat.

redjamjar
  • 819