Java Language Using 'final' to restrict inheritance and overriding


Example

Final classes

When used in a class declaration, the final modifier prevents other classes from being declared that extend the class. A final class is a "leaf" class in the inheritance class hierarchy.

// This declares a final class
final class MyFinalClass {
    /* some code */
}

// Compilation error: cannot inherit from final MyFinalClass
class MySubClass extends MyFinalClass {
    /* more code */
}

Use-cases for final classes

Final classes can be combined with a private constructor to control or prevent the instantiation of a class. This can be used to create a so-called "utility class" that only defines static members; i.e. constants and static methods.

public final class UtilityClass {

    // Private constructor to replace the default visible constructor
    private UtilityClass() {}

    // Static members can still be used as usual
    public static int doSomethingCool() {
        return 123;
    }

}

Immutable classes should also be declared as final. (An immutable class is one whose instances cannot be changed after they have been created; see the Immutable Objects topic. ) By doing this, you make it impossible to create a mutable subclass of an immutable class. That would violate the Liskov Substitution Principle which requires that a subtype should obey the "behavioral contract" of its supertypes.

From a practical perspective, declaring an immutable class to be final makes it easier to reason about program behavior. It also addresses security concerns in the scenario where untrusted code is executed in a security sandbox. (For instance, since String is declared as final, a trusted class does not need to worry that it might be tricked into accepting mutable subclass, which the untrusted caller could then surreptitiously change.)

One disadvantage of final classes is that they do not work with some mocking frameworks such as Mockito. Update: Mockito version 2 now support mocking of final classes.

Final methods

The final modifier can also be applied to methods to prevent them being overridden in sub-classes:

public class MyClassWithFinalMethod {

    public final void someMethod() {
    }
}

public class MySubClass extends MyClassWithFinalMethod {

    @Override
    public void someMethod() { // Compiler error (overridden method is final)
    }
}

Final methods are typically used when you want to restrict what a subclass can change in a class without forbidding subclasses entirely.


The final modifier can also be applied to variables, but the meaning of final for variables is unrelated to inheritance.