Skip to content
April 26, 2011 / marrowboy

“final” countdown

So there I was, working on some code which uses the Java final keyword at every possible opportunity. I mean, literally every concrete method was final, method parameters final – local variables, you’ve guessed it, final. I was confused – I’d never seen this kind of thing before.

I asked the team about why this coding style had been adopted. Answers included:

  • It’s safer – final means immutable, right?
  • For performance reasons.
  • Because the code analysis tool (ie Checkstyle) says so.

In this post I’ll go into a bit of detail about how and where final can be used in Java, and what it means in each situation. First though, lets get one thing clear:

final is not finalize is not finally.

Ok, that’s 3 things. And they’re unrelated: finalize is a method called when an object becomes eligible for GC, finally is used in try, catch, finally. final is a modifier loosely used to mean that something cannot be changed after creation, and is the subject of the rest of this post.

Why are you so upset?

Every time I read a bit of code like:

private final int getAverage( final int a, final int b ){
    final int total = a + b;
    return maximum / 2;
}

I have a little sigh. Fully 4 things in that code are final, three of which are totally unnecessary and the fourth is debatable. What is the writer trying to communicate to other developers? It’s established that developers spend 70% or more of their time working at reading and understanding code – so a conscientious coder should be asking how they can help their colleagues (and future-selves) with everything they write. For the rest of this post I will assume that final should be omitted except where it provides clear benefit, not just thrown around for the sake of it.

Where can we stick this word “final”?

Ok, lets count: We can have final classes, final methods, final member variables, final local variables (which also includes final method parameters andfinal exceptions).

final methods

A final method may not be overridden. Implications:

  • Nobody using your class in a library will be able to override its behaviour. Why are you limiting your users like this?
  • Jmock, Mockito and Easymock are all unable to mock final methods. You’re limiting the testability of your design.
  • private final and static final method declarations are pointless, as neither private nor static methods can be overridden anyway.
  • Twelve years ago there were good performance reasons to use final methods, but this is no longer the case. The fact is that these days javac and hotspot are much better than you are at optimising bytecode. Obligatory Knuth reference: We should forget about small efficiencies, say about 97% of the time. The other 3%, of course, is when you have identified, isolated and tested a performance problem. In my experience this is more like 0.3% of the time (and even then, final won’t help you!). The real facepalm comes when you want to extend or test some code only to find that it has been hamstrung using this bogus reasoning.
  • Repeated for emphasis: while there are some good reasons to use ‘final’, promoting method inlining isn’t one of them

final classes

A final class may not be subclassed. That is all. So:

  • All methods in a final class are also final. A final method in a final class is just noise, and is subject to the same discussions as above.
  • Your mocking library will struggle with a final class. It is possible to do – but if you’re forcing yourself to jump through hoops just to test your code then you must surely have a killer reason to do so, right?
  • A final class with immutable state is a pretty cool thing, as it guarantees that its behaviour will never change over time and will be totally thread-safe. This does not apply to final classes with mutable state, obviously.

final fields

A final field is an interesting thing:

  • Its value must be set in the constructor.
  • It is not immutable just by dint of being final – consider for example a final reference to a Map

final local variables

A final local variable is not an interesting thing:

  • It is not an immutable thing
  • It does not provide any runtime behaviour change. In fact the final does not alter the compiled bytecode at all.
  • “They stop developers from making mistakes”. This is simply incorrect. Good testing and short methods help to stop developers making mistakes. If your developers are likely to accidentally overwrite a variable and not notice then you have big big problems. I have yet to see a single bug caught by this technique.
  • “They communicate the developer’s intent”. Well chosen method names, descriptive tests and careful refactoring are far more important. Given that you’re doing all those anyway (aren’t you?), what use is final?

In conclusion

The final keyword has a lot to answer for, justifying restrictive design and cluttering up codebases. Using final is never ever necessary. Currently my favoured style is to only use final for specifying immutability for thread-safety. As usual, the best advice is to know what you’re doing, and do it on purpose – don’t just spray final around because you think it looks nice. End rant.

Advertisements

One Comment

Leave a Comment
  1. Claus Polanka / May 20 2011 9:47 pm

    I fully agree. Awesome post. Thx so much.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: