135

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?

3
  • 5
    Just throwing this out there - but I've worked on projects where its part of the convention to use final wherever appropriate, so I usually setup eclipse or netbeans to add them to the save actions for the file. That might be why they seem "excessive" - they always do to me too. Do I really need to worry if a reference is immutable in the two lines where it is initialized, used, and discarded? Commented Aug 4, 2011 at 19:58
  • 2
    steve-yegge.blogspot.com/2010/07/…
    – Job
    Commented Aug 4, 2011 at 21:39
  • 1
    Strongly related: programmers.stackexchange.com/questions/48413/…
    – Oak
    Commented Aug 8, 2011 at 18:01

4 Answers 4

151
+100

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.

13
  • 83
    Scala was smart to make val (for an immutable variable) and var (for a mutable one) exactly the same length to type.
    – Ken Bloom
    Commented Aug 4, 2011 at 23:46
  • 31
    The ability to express intent through language semantics rather than flimsey comments is a key to good language design (IMO) Commented Aug 8, 2011 at 17:56
  • 27
    Sorry, but I must disagree on both points. 1) The liberal use of 'final' (IMHO) simply clutters the code without adding value, as when used too often, it becomes habit rather than premeditated intent and 2) premature optimization is a problem you should discuss with your mentor in private, it is not something that should be aired in public code.
    – Paul Smith
    Commented May 16, 2016 at 15:01
  • 31
    If a compiler can spot that an assignment violates final, then it follows that it can also derive when an assignment can be optimised as if it's final, even if it's not explicitly marked final.
    – slim
    Commented May 24, 2016 at 8:29
  • 13
    In Java, using final adds a lot of noise to your code. In Swift where you must choose between "let" and "var" or Scala (must choose between "val" and "var"), the noise aspect is gone, so I'd expect developers to always use the constant form when possible.
    – gnasher729
    Commented Aug 1, 2016 at 18:33
49

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).

6
  • 16
    +1 agree with the final should have been the other way around. Unfortunately they wanted C syntax.
    – user1249
    Commented Aug 8, 2011 at 17:23
  • 4
    Definitely agree that it should have been the other way around. My coding style uses lots of stuff that could be final, but I don't make it final because it makes the code look cluttered and messy. I try to keep methods short so that it's obvious what's going on, though. Commented Aug 8, 2011 at 17:44
  • 12
    +1 for "I'm of the opinion that Java got it backwards..." - couldn't agree more
    – reevesy
    Commented Sep 14, 2014 at 0:44
  • 7
    final doesn't make a non-primitive object immutable, just the reference. So the first point about knowing what the state is, is incorrect. You know that the reference was never bound to a different object, but the state is perfectly mutable.
    – starflyer
    Commented Mar 15, 2018 at 22:37
  • Absolutely agree that Java/C# got it backward. I much prefer the F# style of let being immutable by default and requiring the developer to explicitly write let mutable when they want something to be mutable. All fields in objects should also be immutable by default, like F# record types, so that the state is truly 'final' and not just the reference. Commented Sep 24, 2019 at 12:48
18

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

4
  • 3
    final, though not in the case of an instance variable, does sometimes prevent the overhead of dynamic binding by inlining methods. This will avoid branching on the CPU. In Java, polymorphism is supported unless you specify final whereas in c++ and c#, it is not unless you specify virtual. Not that that really matters on modern CPU's. Anyways, you are correct that it does not optimize instance variables. Commented Aug 11, 2011 at 18:42
  • 4
    Modern JVM's can do this automatically without having to hint with final.
    – user1249
    Commented Jan 9, 2012 at 14:57
  • 1
    +1 for "Also if you see that a variable is not marked with final you know that it will be changed further". This is the real benefit imo.
    – Teimpz
    Commented Jun 11, 2016 at 17:43
  • Regarding the "myth", it was not a Myth before Java 5 (I think). Java 6+ doesn't need final to optimize code if the variable "is final" but doesn't have the keyword. Commented Nov 14, 2016 at 16:18
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.

2
  • 1
    "I doubt putting final on a local variable would ever have made any difference to performance" -- Most JVMs I'm aware of (a bit dated in my knowledge) use a Tree-SSA data structure as an intermediate representation. All assignments spawn a new SSA tree, so this is a safe assumption. By the time they hit the optimization, they don't even know which variable reference it referred back to.
    – ccoakley
    Commented Aug 8, 2011 at 20:30
  • 6
    "I doubt" -> "I haven't measured..."
    – user1249
    Commented Jan 9, 2012 at 14:55

Not the answer you're looking for? Browse other questions tagged or ask your own question.