In Java, you can qualify local variables and method parameters with the final keyword. Doing so results in not being able to reassign x and qwerty in the body of the method.
Having final on methods parameters helps you understand the outgoings of the method at first glance, and draws some attention to those non-final parameters.
The term effectively final variable was introduced in Java 8. A variable is effectively final if it isn't explicitly declared final but its value is never changed after initialization.
final is the only allowed access modifier for local variables. final local variable is not required to be initialized during declaration. final local variable allows compiler to generate an optimized code. final local variable can be used by anonymous inner class or in anonymous methods.
Obsess over:
Consider but use judiciously:
Ignore unless feeling anal:
Method parameters and local variables - I RARELY do this largely because I'm lazy and I find it clutters the code. I will fully admit that marking parameters and local variables that I'm not going to modify is "righter". I wish it was the default. But it isn't and I find the code more difficult to understand with finals all over. If I'm in someone else's code, I'm not going to pull them out but if I'm writing new code I won't put them in. One exception is the case where you have to mark something final so you can access it from within an anonymous inner class.
Edit: note that one use case where final local variables are actually very useful as mentioned by @adam-gent is when value gets assigned to the var in the if
/else
branches.
Is it something I should make an effort to remember to do?
No, if you are using Eclipse, because you can configure a Save Action to automatically add these final modifiers for you. Then you get the benefits for less effort.
The development-time benefits of "final" are at least as significant as the run-time benefits. It tells future editors of the code something about your intentions.
Marking a class "final" indicates that you've not made an effort during design or implementation of the class to handle extension gracefully. If the readers can make changes to the class, and want to remove the "final" modifier, they can do so at their own risk. It's up to them to make sure the class will handle extension well.
Marking a variable "final" (and assigning it in the constructor) is useful with dependency injection. It indicates the "collaborator" nature of the variable.
Marking a method "final" is useful in abstract classes. It clearly delineates where the extension points are.
I use final
all the time to make Java more expression based. See Java's conditions (if,else,switch
) are not expression based which I have always hated especially if your used to functional programming (ie ML, Scala or Lisp).
Thus you should try to always (IMHO) use final variables when using conditions.
Let me give you an example:
final String name;
switch(pluginType) {
case CANDIDATE_EXPORT:
name = "Candidate Stuff";
break;
case JOB_POSTING_IMPORT:
name = "Blah";
break;
default:
throw new IllegalStateException();
}
Now If add another case
statement and do not set name
the compiler will fail. The compiler will also fail if you do not break on every case (that you set the variable). This allows you to make Java very similar to Lisp's let
expressions and makes it so your code is not massively indented (because of lexical scoping variables).
And as @Recurse noted (but apparently -1 me) you can do the preceding with out making String name
final
to get the compiler error (which I never said you couldn't) but you could easily make the compiler error go away setting name after the switch statement which throws away the expression semantics or worse forgetting to break
which you cannot cause an error (despite what @Recurse says) without using final
:
String name;
switch(pluginType) {
case CANDIDATE_EXPORT:
name = "Candidate Stuff";
//break; whoops forgot break..
//this will cause a compile error for final ;P @Recurse
case JOB_POSTING_IMPORT:
name = "Blah";
break;
}
// code, code, code
// Below is not possible with final
name = "Whoops bug";
Because of the bug setting name (besides forgetting to break
which also another bug) I can now accidentally do this:
String name;
switch(pluginType) {
case CANDIDATE_EXPORT:
name = "Candidate Stuff";
break;
//should have handled all the cases for pluginType
}
// code, code, code
// Below is not possible with final
name = "Whoops bug";
The final variable forces a single evaluation of what name should be. Similar to how a function that has a return value must always return a value (ignoring exceptions) the name switch block will have to resolve name and thus bound to that switch block which makes refactoring chunks of code easier (ie Eclipe refactor: extract method).
The above in OCaml:
type plugin = CandidateExport | JobPostingImport
let p = CandidateExport
let name = match p with
| CandidateExport -> "Candidate Stuff"
| JobPostingImport -> "Blah" ;;
The match ... with ...
evaluates like a function ie expression. Notice how it looks like our switch statement.
Here is an example in Scheme (Racket or Chicken):
(define name
(match b
['CandidateExport "Candidate Stuff"]
['JobPostingImport "Blah"]))
Well, this all depends on your style... if you LIKE seeing the final when you won't be modifying the variable, then use it. If you DON'T LIKE seeing it... then leave it out.
I personally like as little verbosity as possible, so I tend to avoid using extra keywords that aren't really necessary.
I prefer dynamic languages though, so it's probably no surprise I like to avoid verbosity.
So, I would say just pick the direction you are leaning towards and just go with it (whatever the case, try to be consistent).
As a side note, I have worked on projects that both use and don't use such a pattern, and I have seen no difference in the amount of bugs or errors... I don't think it is a pattern that will hugely improve your bug count or anything, but again it is style, and if you like expressing the intent that you won't modify it, then go ahead and use it.
I've found marking method parameters and locals as final
is useful as a refactoring aid when the method in question is an incomprehensible mess several pages long. Sprinkle final
liberally, see what "cannot assign to final variable" errors the compiler (or your IDE) throws up, and you just might discover why the variable called "data" ends up null even though several (out of date) comments swear that can't happen.
Then you can fix some of the errors by replacing the reused variables with new variables declared closer to the point of use. Then you find you can wrap whole parts of the method in scoping braces, and suddenly you're one IDE keypress away from "Extract Method" and your monster just got more comprehensible.
If your method is not already an unmaintainable wreck, I guess there might be value in making stuff final to discourage people from turning it into said wreck; but if it's a short method (see: not unmaintainable) then you risk adding a lot of verbosity. In particular, Java function signatures are hard enough to fit into 80 characters as it is without adding six more per argument!
It is useful in parameters to avoid change the parameter value by accident and introduce a subtle bug. I use to ignore this recommendation but after spending some 4 hrs. in a horrible method ( with hundreds of lines of code and multiple fors, nested ifs and all sort of bad practices ) I would recommend you to do it.
public int processSomethingCritical( final int x, final int y ){
// hundreds of lines here
// for loop here...
int x2 = 0;
x++; // bug aarrgg...
// hundreds of lines there
// if( x == 0 ) { ...
}
Of course in a perfect world this wouldn't happen, but.. well.. sometimes you have to support others code. :(
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With