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,274
  • 6
  • 46
  • 71
  • 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? – Steve Jackson Aug 04 '11 at 19:58
  • 2
    http://steve-yegge.blogspot.com/2010/07/wikileaks-to-leak-5000-open-source-java.html – Job Aug 04 '11 at 21:39
  • 1
    Strongly related: http://programmers.stackexchange.com/questions/48413/in-java-should-i-use-final-for-parameters-and-locals-even-when-i-dont-have-to – Oak Aug 08 '11 at 18:01

4 Answers4

149

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
  • 79,623
  • 18
  • 192
  • 283
  • 82
    Scala was smart to make `val` (for an immutable variable) and `var` (for a mutable one) exactly the same length to type. – Ken Bloom Aug 04 '11 at 23:46
  • 31
    The ability to express intent through language semantics rather than flimsey comments is a key to good language design (IMO) – Martin York Aug 08 '11 at 17:56
  • 26
    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 May 16 '16 at 15:01
  • 30
    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 May 24 '16 at 08: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 Aug 01 '16 at 18:33
  • 5
    This post is funny: It makes the intent of the code much more clear ----> ends with ----> The only way to be sure why the author of the code decided to use final is to find him and ask him. OOOOPS!!! may be that the code is not so clean.... – eddieferetro Apr 25 '18 at 09:41
  • 1
    @PaulSmith, It does add value, because the intent is clear, and intent is _critical_ when maintaining code over years with arbitrary numbers of future coders hopped up on caffeine at 3am trying to remember what is _**intended**_ to be immutable or not. See Martin York's comment. – tgm1024--Monica was mistreated Dec 19 '20 at 03:12
  • @tgm1024--Monicawasmistreated I have been maintaining code for over 30 years and the final keyword has never yet proved its use. When the final keyword is used correctly - as in "I, the author of this code, am doing something really clever and tricky so I would really, really appreciate it, if you, the maintainer, (or future me) did not mess with this specific variable which I have labeled final." – Paul Smith Dec 23 '20 at 22:27
  • @tgm1024--Monicawasmistreated (2/2) The alternative is "I, the de-motivated coder who just wants PMD to STFU so that I can commit this turgid POS and get on with my life, will stick in 'final' anywhere and everywhere that this corporate mandated static analysis tool says it could be, regardless of whether or not it should be, because I just don't have the energy left to argue" – Paul Smith Dec 23 '20 at 22:34
  • 1
    @PaulSmith, I suspect this is an emotionally charged issue for you. I've been a software engineer for 4 decades now and I have to say that while I advocate _against_ flamboyancies like both Lippman's and Stoustrup's compound use of `const` everywhere, I have seen use in with `final` in Java, and it's not limited to stateless programming. It's an innocuous mechanism for establishing intent a little more clearly than you're describing. – tgm1024--Monica was mistreated Dec 28 '20 at 16:54
  • @tgm1024--Monicawasmistreated Don't make this personal. The use of 'final' to express intent is a good thing. IMHO, a comment explaining the what and the why of the intent is a far better thing. Using it to stop a static analyzer from complaining is a very, very bad thing because it a) adds excessive noise to code b) obscures the original developers intention and c) encourages coding practices that favor static analyzers instead human maintainers. The fact that final doesn't even do what would be reasonably expected of it just proves it was a poor afterthought. – Paul Smith Dec 29 '20 at 15:06
  • @PaulSmith, static analyzer complaints? No. Enforceability of the original intentions, yes, and those intentions are critical. So to that extent we agree. Where we disagree seems isolated to the viability of comments, which I put no stake in at all. `final` is fairly innocuous, in that it's isolated to the declaration. As with my mention (again you seem to agree), the C++ism of `const` everywhere is simply grotesque. – tgm1024--Monica was mistreated Jan 03 '21 at 21:21
  • 1
    @tgm1024--Monicawasmistreated - I think we can agree on this. I find the abuse of 'final' in Java as offensive as you find 'const' in C++. It is impossible (IMHO) to determine the coders intent unless the term is used sparingly and deliberately, a task made more difficult by static analyzers that insist on its use wherever possible, thereby overriding the coders intent. This is why I give more value to the comment then the keyword. – Paul Smith Jan 04 '21 at 23:24
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).

Chuck
  • 103
  • 2
nerdytenor
  • 763
  • 4
  • 8
  • 15
    +1 agree with the `final` should have been the other way around. Unfortunately they wanted C syntax. –  Aug 08 '11 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. – Adam Jaskiewicz Aug 08 '11 at 17:44
  • 12
    +1 for "I'm of the opinion that Java got it backwards..." - couldn't agree more – reevesy Sep 14 '14 at 00: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 Mar 15 '18 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. – Aaron M. Eshbach Sep 24 '19 at 12:48
  • "once they are bound there is never a question about what their current state is" - That is only true if the object is `immutable` which is unrelated to the `final` status of the variable. I think a lot of people are confusing a read-only _reference_ with an immutable object. – Matt Klein Jan 27 '21 at 22:33
17

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

  • 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. – Jonathan Henson Aug 11 '11 at 18:42
  • 4
    Modern JVM's can do this automatically without having to hint with final. –  Jan 09 '12 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 Jun 11 '16 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. – Martin Marconcini Nov 14 '16 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.

redjamjar
  • 819
  • 1
  • 7
  • 10
  • 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 Aug 08 '11 at 20:30
  • 6
    "I doubt" -> "I haven't measured..." –  Jan 09 '12 at 14:55