Blog-Archiv

Montag, 23. Januar 2017

Apply the final Keyword in Java

Why do we need constants? Why not store everything in variables, like it was done in JavaScript before ES-6 introduced the const keyword? We should stay realistic, in reality nothing is constant. Everything changes, this is the way things are going.

But to find our way in this life, we need to make decisions. We decide based on facts that we know. It is not possible to make decisions upon facts that are not certain, or may change every minute. So we can safely decide only when the facts are constant.


In Java you can declare a constant using the final keyword. You should use it as much as possible, because it makes source code easier to understand, and more robust at runtime. Remember that functional programming languages (e.g. XSLT) do not have variables, they provide constants only. And software written in functional languages is the most resilient in this world. So use final constants as much as you can!

This Blog shows how to use final even in cases where you would think a variable is inevitable.


Inevitable Variable?

Consider following code (your daughter's Saturday afternoon:-)

  boolean canGo = true;

  if (isRaining() == true)
    if (isUmbrellaAvailable() == false)
      canGo = false;

  if (canGo)
    go();
  else
    phone();

If we would change canGo to final, we would get a compile error. Because in case the umbrella is not available, the constant would be re-assigned, and the compiler does not allow that for constants.

But as we insist on using final, we rewrite the code.

Constant Replacement!


  final boolean canGo;

  if (isRaining() == true)
    if (isUmbrellaAvailable() == false)
      canGo = false;
    else
      canGo = true;
  else
    canGo = true;

  if (canGo)
    go();
  else
    phone();

There are voices that deny this solution. Their argument is: the code has become significantly longer, and thus is harder to read.

So here is the short variant:

  final boolean canGo = (isRaining() == false || isUmbrellaAvailable() == true);

  if (canGo)
    go();
  else
    phone();

I admit, this is not always possible so simply. Consider we need several method calls to find out if we can go when it is raining. Then we need the long variant, no way around. But there are always tricks to make it shorter.

  final boolean canGo;

  if (isRaining() == true) {
    final UmbrellaKeeper umbrellaKeeper = GlobalSingletons.get(UmbrellaKeeper.class);
    umbrellaKeeper.promiseMuffin();
    canGo = umbrellaKeeper.isUmbrellaAvailable();
  }
  else {
    canGo = true;
  }

  if (canGo)
    go();
  else
    phone();

Don't Reassign Variables

Here is why I prefer having constants instead of variables:

When a variable is re-assigned, most likely also its semantic has changed.
Then the name of the variable does not fit any more, because it should express its semantic.

So here is my last offer, maybe this can convince you:

  final boolean canGo = true;
  final boolean canGoWeatherChecked = (canGo && isRaining() == false);
  final boolean canGoGearChecked = (canGoWeatherChecked || isUmbrellaAvailable());

  if (canGoGearChecked)
    go();
  else
    phone();

I would call this "semantic solution".

Of course final is not always possible. Consider count-variables like the famous

for (int i = 0; i < array.length; i++)

Implementing such loops using recursive calls is one of the biggest obstacles in functional languages. Here you are glad to have variables. But such numeric variables are (nearly:-) the only cases where you can't use the final modifier.




Keine Kommentare: