Java Code Style: The Final Decision

Home  >>  Common  >>  Java Code Style: The Final Decision

Java Code Style: The Final Decision

On April 28, 2014, Posted by , In Common, By ,,,, , With 6 Comments

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 :D


  1. Effective Java (Second Edition), Chapter 4 – Classes and Interfaces, Joshua Bloch, 2008
  2. Hardcore Java, Chapter 2 – The Final Story, Robert Simmons jr., 2004
  3. Clean Code, Chapter 16, Refactoring SerialDate, Robert C. Martin, 2009
Follow me

Frank Appel

Frank is a stalwart of agile methods and test driven development in particular. He understands software development as a craftsmanship based on a well-balanced mix of knowledge and the experience of the daily work.

fappel@codeaffine.com
Follow me

6 Comments so far:

  1. Jirka Pinkas says:

    Thank you, I had similar experience with final keyword. Do you know / use PMD? I wonder why it sticks out-of-the-box to Joschua Bloch approach.

  2. Rogerio says:

    I think your argument about “test isolation via collaborator mocks” misses the real problem.
    There is no need for mocking of final classes/methods to be “tricky”. For each modern programming language used today, there is at least one mocking tool which does that job just fine. So, the real problem is trying to use a tool that is not fit for the job at hand, namely isolation of collaborator implementations through mocking. With that solved, whether “final” is used or not in the SUT becomes irrelevant.

    • Frank Appel says:

      So what mocking tool do you propose for Java? I am always interested in learning something new ;-)

      • Rogerio says:

        Well, for the Java language you have two options:

        1) PowerMock, if you already uses EasyMock or Mockito (PowerMock is an extension API which adds new abilities, similar to what “EasyMock Class Extension” did for EasyMock).

        2) JMockit, a tool which I develop since 2006. Mocking final classes was one of the main motivations for creating it, in fact (none of the options available at the time – EasyMock and jMock – allowed me to write the unit tests that I wanted to write).

  3. Bob Lauer says:

    As good as they seem, a lot of the practices recommended in Bloch’s book seem to make unit testing more difficult it seems.

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>