Home  Synchronization and concurrency  wait/notify  final  volatile  synchronized keyword  Java threading  Deadlock (and avoiding it)  Java 5: ConcurrentHashMap  Atomic variables  Explicit locks  Queues  Semaphores  CountDownLatch  CyclicBarrier

The Java final keyword

The Java final keyword is very loosely used to indicate that something "cannot change". Specifically— and perhaps confusingly from a language design point of view— it has a number of uses:

  • it is used to indicate that a class cannot be extended;
  • it is used to indicate that a method cannot be overridden;
  • it is used to indicate that a local variable cannot be changed once its value is set;
  • it is used to indicate that a static variable cannot be changed once set, in effect implementing "constants";
  • it is used to indicate that a value of an instance variable cannot be changed once set; this (due to an amendment to the JVM specification as of Java 5) makes accesses to that variable thread safe.

A common misconception about the Java final keyword is that it is essentially a performance optimisation. In Java, final is much more about program design than performance, as we illustrate later when we look at some timings relating to the performance of final as a class modifier.

Using final to indicate that a class or method cannot be overridden

You can use final to specify that a whole class may not be extended, or similarly that a method cannot be overridden.

So when would you use final in this way? A common case is where:

  • a particular method that you are implementing needs to be public (e.g. because it extends some base class that requires it to be public, or simply because you expect callers from outside the package to call it)...
  • ...but you want classes that extend your class not to override your public method, because it contains some logic that you don't want replacing.

As an example, imagine if we were implementing a template for a swing component which would have a number of subclasses, but whose subclasses would always need to draw content on the "left" and "right" side of the component, at specific coordinates. We would probably therefore implement our template component as a subclass of JComponent, requiring a public paintComponent() method:

public abstract class LeftAndRightComponent extends JComponent {
  ...

  public void paintComponent(Graphics g) {
    // calculate x and y for left side
    ...
    paintLeftSide(x, y);
    // calculate x and y for right side
    ...
    paintRightSide(x, y);
  }

  protected abstract void paintLeftSide(int x, int y);

  protected abstract void paintRightSide(int x, int y);

}

But now we have the problem that overriding classes, as well as implementing paintLeftSide() and paintRightSide(), could "accidentally" override paintComponent() itself, in effect removing the whole functionality of the class! The solution is to declare this method final:

public abstract class LeftAndRightComponent extends JComponent {
  ...
  public final void paintComponent(Graphics g) {
    ...
    paintLeftSide(x, y);
    ...
    paintRightSide(x, y);
  }
  ...
}

Now, a subclass can still override paintLeftSide() and paintRightSide(), but not paintComponent, which is declared final.

Final classes

Cases for making an entire class final are less common, but would essentially be where allowing a subclass with differing implementation could lad to unexpected behaviour. A notable example from the JDK itself is the String class. A central design decision of Java strings is that they are immutable, and some of the inner workings of strings are tightly coupled with internals of the JVM itself. These factors together mean that allowing subclasses of String could lead to some unexpected behaviour, and so the String class is defined as being final:

public final class String {
  ...
}

Article written by Neil Coffey (@BitterCoffey).

Software

 LetterMeister (word puzzle game for iPhone)
 Currency Quoter (currency converter/predictor)
 French Vocab Games for iPhone/iPad
 Vocabularium: create Spanish vocab podcasts


Java programming articles and tutorials on this site are written by Neil Coffey (@BitterCoffey). Suggestions are always welcome if you wish to suggest topics for Java tutorials or programming articles, or if you simply have a programming question that you would like to see answered on this site. Most topics will be considered. But in particular, the site aims to provide tutorials and information on topics that aren't well covered elsewhere, or on Java performance information that is poorly described or understood. Suggestions may be made via the Javamex blog (see the site's front page for details).
Copyright © Neil Coffey 2015. All rights reserved.