I consider final
in method parameters and local variables to be code noise. Java method declarations can be quite long (especially with generics) - there's no need to make them any longer.
Unit tests can cover that
If unit tests are written properly, assigning to parameters that is "harmful" will be picked up, so it should never actually be a problem. Visual clarity is more important than avoiding a possible bug that isn't picked up because your unit tests have insufficient coverage.
Static code analysis can help
Tools like Sonar, FindBugs and CheckStyle can be configured to break the build if assignment is made to parameters or local variables, if you deeply care about such things.
Use in anonymous class
Of course, if you need to make them final, for example because you're using the value in an anonymous class, then no problem - that's the simplest cleanest solution.
Strive for readable code that is simple
Apart from the obvious effect of adding extra keywords to your parameters, and thereby IMHO camouflaging them, adding final to method parameters can often make the code in the method body become less readable, which makes the code worse - to be "good", code must be as readable and as simple as possible. For a contrived example, say I have a method that needs to work case insensitively.
Without final
:
public void doSomething(String input) {
input = input.toLowerCase();
// do a few things with input
}
Simple. Clean. Everybody knows what's going on.
Now with 'final', option 1:
public void doSomething(final String input) {
final String lowercaseInput = input.toLowerCase();
// do a few things with lowercaseInput
}
While making the parameters final
stops the coder adding code further down from thinking he's working with the original value, there's an equal risk that code further down may use input
instead of lowercaseInput
, which it shouldn't and which can't protected against, because you can't take it out of scope (or even assign null
to input
if that would even help anyway).
With 'final', option 2:
public void doSomething(final String input) {
// do a few things with input.toLowerCase()
}
Now we're just created even more code noise and introduced a performance hit of having to invoke toLowerCase()
n times.
With 'final', option 3:
public void doSomething(final String input) {
doSomethingPrivate(input.toLowerCase());
}
/** @throws IllegalArgumentException if input not all lower case */
private void doSomethingPrivate(final String input) {
if (!input.equals(input.toLowerCase())) {
throw new IllegalArgumentException("input not lowercase");
}
// do a few things with input
}
Code Noise
Talk about code noise. This is a train wreck. We've got a new method, a required exception block, because other code may invoke it incorrectly. More unit tests to cover the exception. All to avoid one simple, and IMHO preferable and harmless, line.
There's also the issue that methods should not be so long that you can't easily visually take it in and know at a glance that an assignment to parameter has taken place.
I do think it is good practice/style that if you assign to a parameter you do it every early in the method, preferably first line or straight after basic input checking, effectively replacing it for the entire method, which has a consistent effect within the method. Readers know to expect any assignment to be obvious (near the signature declaration) and in a consistent place, which greatly mitigates the problem that adding final is trying to avoid. Actually I rarely assign to parameters, but if I do I always do it at the top of a method.
Note also that final
doesn't actually protect you like it may at first seem:
public void foo(final Date date) {
date.setTime(0);
// code that uses date
}
final
doesn't completely protect you unless the parameter type is primitive or immutable.
final
or not, and optimized accordingly. Modern compilers are smart enough to figure it out for themselves. At least on local variables,final
is strictly for the benefit of human readers. If your routines are not too complicated, then most human readers should be able to figure it out for themselves too.