Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

This question already has an answer here:

Studying some classes of Android, I realized that most of the variables of methods are declared as final.

Example code taken from the class android.widget.ListView:

/**
* @return Whether the list needs to show the top fading edge
*/
private boolean showingTopFadingEdge() {
    final int listTop = mScrollY + mListPadding.top;
    return (mFirstPosition > 0) || (getChildAt(0).getTop() > listTop);
}

/**
 * @return Whether the list needs to show the bottom fading edge
 */
private boolean showingBottomFadingEdge() {
    final int childCount = getChildCount();
    final int bottomOfBottomChild = getChildAt(childCount - 1).getBottom();
    final int lastVisiblePosition = mFirstPosition + childCount - 1;
    final int listBottom = mScrollY + getHeight() - mListPadding.bottom;
    return (lastVisiblePosition < mItemCount - 1)
                     || (bottomOfBottomChild < listBottom);
}

What is the intention of using the final keyword in these cases?

share|improve this question

marked as duplicate by gnat, GlenH7, MichaelT, Yusubov, psr Aug 13 '13 at 1:05

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. –  Job Oct 22 '11 at 5:14
2  
1  
Probably they're in place to pass static code analysis tools such as PMD. –  Spoike Oct 22 '11 at 7:36

7 Answers 7

up vote 23 down vote accepted

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.

share|improve this answer
2  
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 Carnahan Oct 22 '11 at 11:42
4  
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". –  Jon Dec 3 '11 at 10:46
    
well, ya, but there are a couple of good reasons behind the habit –  Rob Y Feb 21 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:

final int result;
if (/* something */) {
  if (/* something else */) {
    result = 1;
  }
  else if (/* some other thing */) {
    result = 2;
  }
}
else {
  result = 3;
}
System.out.println(result);

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 everything final 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:

int result = 0;

// OK, time to cover all the cases!
if (/* something */) {
  if (/* something else */) {
    result = 1;
  }
  else if (/* some other thing */) {
    result = 2;
  }
  // Whoops, missed an "else" here. Too bad.
}
else {
  result = 3;
}
System.out.println(result);  // Works fine!

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.

share|improve this answer
1  
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 Taylor Oct 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 Carnahan Oct 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. –  Jon Dec 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 –  minopret Feb 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. –  crazy2be Aug 9 '13 at 21:54

We can't know the answer for sure (unless we ask the original developers), but my guesses are:

  1. The programmers of these methods may have felt that adding "final" better expresses the purpose of those variables.
  2. The programmers may be using a tool that automatically add "final" where it can.
  3. It could be an optimisation trick: I don't have the knowledge / tools to verify this myself, but would be interested to know either way.
share|improve this answer

To make silly mistakes less frequent. final makes sure that the variable always points to its first-assigned object, and any attempted changes will count as a compile-time error.

You could also ask "why explicitly declare the type of a variable?", or "why declare methods as constant in C++?". Same reason.

share|improve this answer

Another reason is to be able to use them in inner anonymous classes:

public interface MyInterface {
    void foo();
} 

void myMethod() {
    final String asdf = "tada";//if not final cannot be used in inner classes
    new MyInterface() {
        @Override
        public void foo() {
             String myNewString = asdf;//does not compile only if asdf is final
        }
    }
}
share|improve this answer

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.

share|improve this answer

Here the reason why: Avoiding reassignment to local variables/parameters. This would increase readability and avoid some stupid bugs.

http://sourcemaking.com/refactoring/remove-assignments-to-parameters

Excerpt:

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.

share|improve this answer

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