Java Code Style: The Final Decision
Isn’t it funny how the alleged most unremarkable things can lead to controversial discussions or sometimes even heated debates with hardend fronts? I witnessed on several occassions for example, how the usage of the keyword final
triggered quite passionate arguments. And for an outside observer this might have looked as if the ultimate decision about being evil or divine was at stake.
However it must be said in all fairness, most of the possible final
use cases hardly fit into a simple right or wrong pattern. The choice about to use or not to use rather depends on the individual emphasis of often contradictorily intentions.
Seeking for advice in literature, the only halfway common ground seems to be the final constants definition…
class Foo { public static final String CONSTANT = "constantValue"; }
… and Joshua Bloch’s Item 15: Minimize mutability1, where he recommends to make all fields of an immutable class final
and to ensure, that the class cannot be extended (whereas the latter does not mandatorily need to be achieved by final
):
public final class Foo { private final int value; public Foo( int value) { this.value = value; } public int getValue() { return value; } [...] }
From there opinons diverge. Robert Simmons jr. has dedicated an entire chapter on the final
keyword in his book Hardcore Java2, which he concludes with the strong advice to ‘spread final all over your code’. This well written chapter contains a lot of insights about the advantages of converting logical errors into compile time errors by declaring variables, parameters, methods or classes final
.
On the other hand Robert C. Martin explicitly disagrees with the following statement: ‘there are a few good uses for final
, such as the occasional final
constant, but otherwise the keyword adds little value and creates a lot of clutter’3. Continuing he explains, that the kind of errors final
might catch are usually covered by his unit tests.
While I tend to agree with Martin I would not say Simmons is generally wrong. In the past I actually used the final
keyword often by myself with the intent to avoid programming mistakes or misuse. One reason for changing my mind, though, is probably my shift to the TDD approach a couple of years ago.
By doing so I noticed – additionally to Martin’s argument – achieving test isolation via collaborator mocks gets quite more tricky, if the collaborator class or some of its methods are declared as final
. As testing hardly can be considered misuse, it made me think of the far reaching consequences such declarations can imply. I got aware of how difficult it is to foresee, that there will be no valid use case, which would justify extension and overriding.
On the contrary, confronted with final
methods or classes, people sometimes get quite inventive to somehow circumvent the restrictions, making things probably worse than e.g. class extension would have been. Because of this I nowadays usually refrain from using the keyword on classes and method declarations and confine myself to a not-to-be-intended-for-sub-classing note or the like in the documentation.
Before this post is drawing to its end, I like to share a last thought regarding the cluttering topic mentioned above. To do so please have a look at the following code, which relies on final
for method scoped variables and parameters:
public void doit( final String message ) { final int value = calculate(); final Item item = create( value, message ); executorService.submit( new Runnable() { public void run() { handle( item ); } } ); }
Although the code is quite useless and can be arranged differently, it reflects some real coding style with respect to final
I stumbled across recently. While this style prevents reassignment of local variables on accident, it also disguises the fact, that one final
declaration is actually mandatory. This is because the variable item
is used within the annonymous Runnable
implementation. The next snippet gets rid of the unneeded declarations to stress the difference:
public void doit( String message ) { int value = calculate(); final Item item = create( value, message ); executorService.submit( new Runnable() { public void run() { handle( item ); } } ); }
Weighing the pros and cons I prefer the last variant, but I assume depending on your personal point of view, the capabilities of your IDE to quit local reassigments with warnings, the coding conventions of your team, and, and, and, you will probably have good reasons to choose either the first or the second style or even favor a mix of both.
Which leads me to the final conclusion, that the controversy will rage on!
- Effective Java (Second Edition), Chapter 4 – Classes and Interfaces, Joshua Bloch, 2008 ↩
- Hardcore Java, Chapter 2 – The Final Story, Robert Simmons jr., 2004 ↩
- Clean Code, Chapter 16, Refactoring SerialDate, Robert C. Martin, 2009 ↩
Reference: | Java Code Style: The Final Decision from our JCG partner Frank Appel at the Code Affine blog. |
When writing any code, one can never imagine the scenario future users and maintainers will run into. For this reason, one should never assume noone will ever need to extend/override something. Putting finals all over is believing in own omnscience, and in my opinion wrong by definition. Intended usage should be communicated through comments even if it initially appears dirtier, and the user should be allowed to make use of the existing code in any way they see fit. The code was written for them anyway.
There is one more thing to say about the final modifier.
If you use it on methods it does impact the performance of your Program!
The Compiler is then no longer forced to look in further extended classes if the method has been overridden.