Isn’t it funny how the alleged most unremarkable things can lead to controversial discussions or sometimes even heated debates with hardened fronts? I witnessed on several occasions, for example, how the usage of the Java final keyword 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 Java final keyword 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 mutability , 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, opinions diverge. Robert Simmons Jr. has dedicated an entire chapter on the final keyword in his book Hardcore Java , 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’ . 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 Java 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 Java final 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 clutter 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 (Update 2015/10/07: this was written prior Java 8). 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 reassignments 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 :D

Title Image: © Depositphotos.com/Aquir014b