57

In Java, you can qualify local variables and method parameters with the final keyword.

public static void foo(final int x) {
  final String qwerty = "bar"; 
}

Doing so results in not being able to reassign x and qwerty in the body of the method.

This practice nudges your code in the direction of immutability which is generally considered a plus. But, it also tends to clutter up code with "final" showing up everywhere. What is your opinion of the final keyword for local variables and method parameters in Java?

ordnungswidrig
  • 3,140
  • 1
  • 18
  • 29
Julien Chastang
  • 17,592
  • 12
  • 63
  • 89
  • 2
    See http://stackoverflow.com/questions/266806/is-there-any-performance-reason-to-declare-method-parameters-final-in-java#266981 and http://stackoverflow.com/questions/137868/using-final-modifier-whenever-applicable-in-java and http://stackoverflow.com/questions/154314/when-to-use-final – Robin Nov 25 '08 at 14:36

12 Answers12

53

You should try to do this, whenever it is appropriate. Besides serving to warn you when you "accidentally" try to modify a value, it provides information to the compiler that can lead to better optimization of the class file. This is one of the points in the book, "Hardcore Java" by Robert Simmons, Jr. In fact, the book spends all of its second chapter on the use of final to promote optimizations and prevent logic errors. Static analysis tools such as PMD and the built-in SA of Eclipse flag these sorts of cases for this reason.

rjray
  • 5,525
  • 4
  • 31
  • 37
  • 8
    +1: Just one addition - `final` also convey's the author's _intent_, both in parameters and local variables. – Ken Gentle Nov 25 '08 at 12:58
  • 3
    I'm reading Hardcore Java right now. I thought I knew java........... – WolfmanDragon Dec 09 '08 at 21:25
  • 2
    Are you sure final locals/method parameters can cause the compiler to optimize better? For a counter point, imagine if you declare a local variable `int x = 2`. If you **unconditionally** never reassign `x`, the compiler **will** know this, because by scanning the entire code body and seeing that `x` cannot possibly be reassigned no matter what condition, it deducts that `x` will never be modified... – L̲̳o̲̳̳n̲̳̳g̲̳̳p̲̳o̲̳̳k̲̳̳e̲̳̳ Jun 27 '10 at 23:51
  • 5
    Ironic that PMD doesn't use final method parameters in their own source code, to give one example. Nor does most of the JDK that I've looked at. Nor do the Eclipse refactorings for, say, encapsulation. – Dan Rosenstark Oct 03 '10 at 23:44
  • 1
    @Yar many Eclipse refactorings and source generation/completion templates are not examplary... – Gabriel Ščerbák Nov 18 '10 at 12:32
  • @Gabriel Ščerbák my point was that I'm not the only person that thinks that `final` on input parameters clutters code for little or no gain in clarity. – Dan Rosenstark Nov 18 '10 at 16:31
  • @Yar I am not entirely sure that is a good thing. It is ignoring a capability of a language because it is not designed well. I don't like the way it works, but I am more confident with compiler checking access than believing developers won't ever try to do that. The fact that it is not done nicely is problem Oracle should solve, not programmers. As for the clutter, I prefer finding final parameters rather than scanning through code if the parameter is not modified. – Gabriel Ščerbák Nov 18 '10 at 18:42
  • @Gabriel Ščerbák, final instance variables (or statics, of course) are perfect. I just question the need to mark parameters final, because it doesn't actually change the CALLER'S behavior, so why is it part of the signature? And who cares if the method implementer wants to reuse a variable, but why would they do that? There are a lot of letters to make new variables from, right? Most importantly, though, is WHY WOULD YOU MAKE THIS RESTRICTION A PRIORI? If the variable `point` gets converted and you still call it `point`, that's your business as a method implementer. Doesn't affect the caller. – Dan Rosenstark Nov 18 '10 at 20:43
  • 1
    @Yar AFAIK you are mistaken in the point that it is a part of the signature, actually, you don't need to specify parameters in an interface as final, final in implementation is enough. I agree reusing variables can (and should) be omitted, final keyword just let you state it explicitly. My opinion is as written before, it should be implicit part of language without syntax support. Until then I will use it with help from my IDE. – Gabriel Ščerbák Nov 19 '10 at 04:31
  • Making method parameters final can't affect performance, because it's not part of the compiled classfile. Personally, I don't do this (it clutters the code significantly and it's important for method signatures to be readable... and it's easier to just have good habits!), though if you are debugging a poorly-written and overly-long method, it could make sense to add "final" to everything as a quick way to see if there are reassignment problems in there. – Rob Whelan Apr 23 '11 at 15:32
27

My personal opinion is that it is a waste of time. I believe that the visual clutter and added verbosity is not worth it.

I have never been in a situation where I have reassigned (remember, this does not make objects immutable, all it means is that you can't reassign another reference to a variable) a variable in error.

But, of course, it's all personal preference ;-)

SCdF
  • 57,260
  • 24
  • 77
  • 113
  • 5
    +1 because I think that it's not only about the method body and logic errors (into which I've never ran just because of non-final variables, FWIW), but also about readable method signatures. I can't see how a parameter declared as final makes the signature more readable. Simple types are passed by values, so are not modifiable. Complex types are passes by reference, but the reference is passed by value, so is not modifiable. Final is just noise for a reader of the signature. – mxk Jul 18 '10 at 11:17
8

Making a parameter final guarantees that the value used at any location in the method refers to the value passed. Otherwise you have to parse mentally all the code above a given location to know what value the parameter has at that point.

Hence, not using final makes your code less readable, and maintainable, all by itself :)

Final local variables depend on intent, and is less important in my point of view. Depends on what goes on.

Thorbjørn Ravn Andersen
  • 73,784
  • 33
  • 194
  • 347
  • Please beware that final only marks the reference as immutable. The properties of the referenced object can change at any time. Thus you'll only gain this level of assurance if you make the whole object graph immutable. This is nevertheless a very good practice even thow it's hard to achieve in java. – ordnungswidrig Nov 21 '11 at 09:41
  • It guarantees that the object referred to is the same. The _contents_ of said object may, naturally, change. – Thorbjørn Ravn Andersen Nov 21 '11 at 09:56
6

In the case of local variables, I tend to avoid this. It causes visual clutter, and is generally unnecessary - a function should be short enough or focus on a single impact to let you quickly see that you are modify something that shouldn't be.

In the case of magic numbers, I would put them as a constant private field anyway rather than in the code.

I only use final in situations where it is necessary (e.g., passing values to anonymous classes).

Uri
  • 88,451
  • 51
  • 221
  • 321
5

Because of the (occasionally) confusing nature of Java's "pass by reference" behavior I definitely agree with finalizing parameter var's.

Finalizing local var's seems somewhat overkill IMO.

Community
  • 1
  • 1
javamonkey79
  • 17,443
  • 36
  • 114
  • 172
  • But if you pass a List by reference and mark it as "final" in the parameter list, you can still add or remove elements and see them reflected in the caller - this is surely MORE confusing than not putting "final" on the parameter in this case? – mjaggard Jan 30 '12 at 14:46
  • Not necessarily. Object mutability is a fairly novice concept IMO. Where I work, we expect devs to understand that a final Object does not mean that it can't change, just that it can't be re-referenced. – javamonkey79 Jan 30 '12 at 16:15
3

Yes do it.

It's about readability. It's easier to reason about the possible states of the program when you know that variables are assigned once and only once.

A decent alternative is to turn on the IDE warning when a parameter is assigned, or when a variable (other than a loop variable) is assigned more than once.

Craig P. Motlin
  • 26,452
  • 17
  • 99
  • 126
  • finalized wont preserve a parameter or variable from become modified, it is not like const in C++. Pass list to a final parameter an you can clear it anyway. – Arne Burmeister Jan 03 '09 at 20:29
  • It's not about safety, it's about readability. Obviously making a parameter final has no effect on which states are possible at the end of the method. – Craig P. Motlin Jan 05 '09 at 16:24
  • 2
    @Motlin: it does for primitives and immutable objects, which covers a lot of parameters in my experience. – Andrew Swan Feb 12 '09 at 22:07
  • 1
    @Andrew I'm talking about state on the heap, not on the stack which is about to get lost anyway. There are no side effects that are possible with non-final parameters that you can't do with final parameters. – Craig P. Motlin Feb 12 '09 at 23:11
2

final has three good reasons:

  • instance variables set by constructor only become immutable
  • methods not to be overridden become final, use this with real reasons, not by default
  • local variables or parameters to be used in anonimous classes inside a method need to be final

Like methods, local variables and parameters need not to be declared final. As others said before, this clutters the code becoming less readable with very little efford for compiler performace optimisation, this is no real reason for most code fragments.

Arne Burmeister
  • 20,046
  • 8
  • 53
  • 94
2

Although it creates a little clutter, it is worth putting final. Ides e.g eclipse can automatically put the final if you configure it to do so.

fastcodejava
  • 39,895
  • 28
  • 133
  • 186
2

Making local variables and method parameters final is essential if you want to pass those parameters into anonymous classes - like you instantiate an anonymous Thread and want to access those params in the body of the run() method.

Apart from that I am not sure of the performance benefits w.r.t better performance through compiler optimization. It is up to the specific compiler implementation whether it wants to optimize it at all...

It will be good to know of any performance stats from using final ...

kartheek
  • 763
  • 3
  • 7
0

Why would you want to? You wrote the method, so anyone modifying it could always remove the final keyword from qwerty and reassign it. As for the method signature, same reasoning, although I'm not sure what it would do to subclasses of your class... they may inherit the final parameter and even if they override the method, be unable to de-finalize x. Try it and find out if it would work.

The only real benefit, then, is if you make the parameter immutable and it carries over to the children. Otherwise, you're just cluttering your code for no particularly good reason. If it won't force anyone to follow your rules, you're better off just leaving a good comment as you why you shouldn't change that parameter or variable instead of giving if the final modifier.

Edit

In response to a comment, I will add that if you are seeing performance issues, making your local variables and parameters final can allow the compiler to optimize your code better. However, from the perspective of immutability of your code, I stand by my original statement.

Elie
  • 13,693
  • 23
  • 74
  • 128
  • The JRE or compiler can do more optimization if it knows the object is finalized. – paxdiablo Nov 25 '08 at 04:25
  • Sure, but that wasn't the question. In terms of making your code immutable, it doesn't really work. However, you are quite correct in that it can be slightly faster than not using it, and should be considered when performance is an issue. – Elie Nov 25 '08 at 04:27
  • As I commented on Pax's answer, I'm fairly sure there are no perf improvements by making local variables final, since the JVM can guess that for you. – SCdF Nov 25 '08 at 04:31
  • No, just compiler improvements, but who cares about those. Now I'm too lazy to correct myself yet again. Oh well.... – Elie Nov 25 '08 at 04:34
  • Finalizing the parameter is not an optimization. The final flag is stripped out at compile time. It is only used by the compiler, not at runtime. – Robin Nov 25 '08 at 14:32
0

I let Eclipse do it for me when they are being used in an anonymous class, which is increasing due to my use of Google Collection API.

Miserable Variable
  • 28,432
  • 15
  • 72
  • 133
0

We do it here for the local variables if we think they will not be reassigned or should not be reassigned.

The parameters are not final since we have a Checkstyle-Check which checks for reassigning parameters. Of course nobody would ever want to reassign a parameter variable.

boutta
  • 24,189
  • 7
  • 34
  • 49