This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.

11

One can flip this around and ask: why declare non-final one-time variables inside a method? Perhaps they make it final unless it absolutely does not need to be. I would say that this is not a bad practice - you are more likely to avoid a couple of bugs, save a few seconds for some readers. Also, seasoned C++ hackers might get a lukewarm, albeit not warm, semi-fuzzy feeling from using final, which is like const. Doing this has the same benefit as what I call "assert-driven development". Since what can go wrong will go wrong, why not take cheap insurance against it? State modification canb evil.
–
JobOct 22 '11 at 5:14

7 Answers
7

I would say that this is due to force of habit. The programmer that wrote this code knew as he was writing it that the values for the final variables should never be changed after assignment, and so made them final. Any attempt to assign a new value to a final variable after assignment will result in a compiler error.

As habits go, it's not a bad one to develop. At the least, making a variable final specifies the intent of the programmer at the time of writing. This is important as it might give subsequent programmers who edit the code pause for thought before they start changing how that variable is used.

I would add (and did add in my answer) that declaring variables final by default is also a good habit because it encourages you do make fields final by default as well.
–
Joe CarnahanOct 22 '11 at 11:42

5

Agreed. It's a good habit to get into along with a number of others; eg: "Make everything final by default, unless otherwise required", "Make everything private by default, unless otherwise required".
–
JonDec 3 '11 at 10:46

well, ya, but there are a couple of good reasons behind the habit
–
Rob YFeb 21 '14 at 15:33

Speaking as a Java developer who makes all variables final by default (and who appreciates the fact that Eclipse can do this automatically), I find it easier to reason about my program if variables are initialized once and never changed again.

For one thing, uninitialized variables are no longer any concern, because trying to use a final variable before it has been initialized will result in a compile error. This is particularly useful for nested conditional logic, where I want to make sure that I covered all the cases:

Did I cover all the cases? (Hint: No.) Sure enough, this code won't even compile.

One more thing: In general, any time you know that something is always true about a variable, you should try to get your language to enforce it. We do this every day when we specify a variable's type, of course: The language will ensure that values that are not of that type cannot be stored in that variable. Likewise, if you know that a variable should not be reassigned because it already has the value that it should keep for the entire method, then you can get the language to enforce that restriction by declaring it final.

Lastly, there's the matter of habit. Others have mentioned that this is a habit (+1 to Jon for that), but let me say something about why you would want this habit. If you are declaring fields in your class and not local variables in a method, then it's possible for multiple threads to access those fields at the same time. There are some obscure exceptions, but in general, if a field is final, then every thread that uses your class will see the same value for the variable. Conversely, if a field is not final and multiple threads are using your class, you will need to worry about explicit synchronization using synchronized blocks and/or classes from java.util.concurrent. Synchronization is possible, but programming is hard enough already. ;-) So, if you just declare everythingfinal out of habit, then many of your fields will be final and you'll spend as little time as possible worrying about synchronization and concurrency-related bugs.

For more on this habit, check out the "Minimize Mutability" tip in Joshua Bloch's Effective Java.

Edit: @Peter Taylor has pointed out that the example above would also not compile if the final keyword is removed, which is completely correct. When I advised in favor of keeping all local variables final, it's because I wanted to make examples like the following one impossible:

Using a new variable instead of reusing an old one is how I can tell the compiler that trying to cover the complete universe of possibilities, and using final variables forces me to use a new variable instead of recycling an old one.

Another valid complaint about this example is that you should avoid complex nested conditional logic in the first place. That's true, of course, precisely because it's hard to make sure you covered all the cases in the way that you intended. However, sometimes complex logic can't be avoided. When my logic is complex, I want my variables to be as simple to reason about as possible, which I can achieve by making sure my variables' values never change after they are initialized.

For one thing, uninitialized variables are no longer any concern, because trying to use a final variable before it has been initialized will result in a compile error. If removing the final keyword makes your example compile, you're using a defective compiler. Or, in other words, you've dedicated half of your post to a misleading statement. (If you wrote it in terms of a field rather than a variable then it would be a case where final makes a difference, but would become irrelevant to the question - just as your third point already largely is).
–
Peter TaylorOct 22 '11 at 14:16

The alternative to the code snippet that I had in mind isn't just the same code snippet with the word "final" removed. I'll edit my answer to make the alternative explicit.
–
Joe CarnahanOct 23 '11 at 16:19

Good answer. Far more comprehensive than mine. I'd like to second the recommendation for "Effective Java", specifically the section on immutable objects, which is relevant to the discussion.
–
JonDec 3 '11 at 10:44

"Programmers are not to be measured by their ingenuity and their logic but by the completeness of their case analysis." -- Alan Perlis, "Epigrams in Programming", reproduced here: cs.yale.edu/quotes.html
–
minopretFeb 12 '13 at 20:49

Personally, I would write your example something like int result = someFunctionWithComplexLogic(), and then allow the compiler to ensure that function always returns a value. This also often simplifies complex logic- your example becomes if (!/* something */) return 4; else if (/* something else */) return 1; else if (/* some other thing */) return 2;, which is much simplified from your original example. It's also trivial to see just by inspection (although the compiler will also verify it for you) that all of the cases are not handled.
–
crazy2beAug 9 '13 at 21:54

Honestly, I don't think there would be a real reason to make a variable final in this context. I suppose they either copy and pasted the code, or they just really want to discourage anyone who adds more code to that method from making reassignments to those variables.

Java 1.1 and later versions allow you to mark a parameter as final;
this prevents assignment to the variable. It still allows you to
modify the object the variable refers to. I always treat my parameters
as final, but I confess I rarely mark them so in the parameter list.