The Final Word on “final”
In Java, overuse of
final feels like SHOUTING. It’s outdated and inappropriate much of the time.
This is mainly about the
final keyword in Java, but my opinion on its counterpart
const is a good thing and
final is a bad thing needs some unpacking.
var tends to do something I disagree with. On the whole, a variable should not need reassigning after it’s first given a value. That’s not true with accumulators, or certain looping situations, but it’s more true than it’s not.
Many refactorings I propose are of the formula stop reassigning that temporary variable and delegate to a function that chooses an answer and returns it.
So my premise is that code, largely, should work on the premise that all variables are to be treated as single-assignment by default.
Let’s Enforce It Then?
Why shouldn’t we enforce it in Java?
Java already has the concept of effectively final which brings the benefits of final to constructs which need to trust something is final – i.e. lambda functions and anonymous inner classes. Essentially the compiler already knows what’s final, and for me adding
final on top feels like shouting. It certainly makes the code busier… less is more, and
final feels like overcrowding.
How Can We Trust Ourselves?
Yes, but how do I know something really is
final if I don’t say it’s final. What if someone changes it?
The above code guarantees that
item inside the loop can’t be redefined. Number 1 – WHO CARES!? Number 2 – the method is very short. If a Ninja came up and tried to mutate the value of
item you’d notice it with short functions.
And that’s the point. If you have very short functions and keep your code modular, you can see what’s going on. You have no surprises and you can spot variables that change vs references that don’t.
Don’t make me follow your thought process a word at a time with
final as the seasoning peppering the text. Make sentences of your code that explain whole thoughts and only add variables and modifiers if you need to.
Where Does Final Come In?
final judiciously. I should say that I make all the child-services of my bean components/services in Spring
private final inside my classes, but I don’t. There’s an argument for it, namely that the wiring of the services inside an application context is innately immutable, but I tend not to. If you did, I’d not argue.
I have two key use cases where
final is a MUST!
They’re both about the importance of SHOUTING and Immutability.
- Global constants MUST be signposted as such
- Implementing the immutable pattern requires
finaland should also be signposted
So you’ll always find me using
private static final SomeType SOME_CONSTANT_IN_CAPITALS in class-level constants used within the class or as global variables, because they’re special and MUST be treated as constants with extra protection – the convention is strong and the danger of mistreatment much higher than a local variable in a single function.
You’ll find me wanting the immutable pattern implemented properly.
People who’ve studied for job interviews and know that
final also protects things from being overridden can feel smug at this stage until I say that I’m not really that interested in that usage of it. If you’re trying to prevent a programmer from having flexibility, or trying to satisfy checkstyle or Sonar by making something
final because it says so, then Meh!
But if you want truly immutable objects for some high cause, then I salute you.
When I start writing immutable data objects stored in caches and shared by multiple threads, you won’t be able to stop me from
finaling my way through it.
I’ll move your logger and your reference data into
static final BLOCK_CAPITAL_NAME d things every day of the week.
Most importantly, though: replace ALL “final ” with “” is still some of the most satisfying refactoring I’ve ever done.
|Published on Java Code Geeks with permission by Ashley Frieze, partner at our JCG program. See the original article here: The Final Word on “final”|
Opinions expressed by Java Code Geeks contributors are their own.