How to Prevent Inheritance in Java Using the Keyword Final

Avoid Corrupting the Behavior of a Class by Avoiding Inheritance

While one of Java's strengths is the concept of inheritance, in which one class can derive from another, sometimes it's desirable to prevent inheritance by another class. To prevent inheritance, use the keyword "final" when creating the class.

For example, if a class is likely to be used by other programmers, you may wish to prevent inheritance if any subclasses created could cause problems. A typical example is the String class.

If we wanted to create a String subclass:

 public class MyString extends String{
 
 } 

We would be faced with this error:

 cannot inherit from final java.lang.String 

The designers of the String class realized that it was not a candidate for inheritance and have prevented it from being extended.

Why Prevent Inheritance?

The main reason to prevent inheritance is to make sure the way a class behaves is not corrupted by a subclass.

Suppose we have a class Account and a subclass that extends it, OverdraftAccount. Class Account has a method getBalance():

  public double getBalance()
  {
    return this.balance;
  } 

At this point in our discussion, subclass OverdraftAccount has not overridden this method.

(Note: For another discussion using this Account and OverdraftAccount classes, see how a subclass can be treated as a superclass).

Let's create an instance each of the Account and OverdraftAccount classes:

 Account bobsAccount = new Account(10);
 bobsAccount.depositMoney(50);

 OverdraftAccount jimsAccount = new OverdraftAccount(15.05,500,0.05);
 jimsAccount.depositMoney(50);

 //create an array of Account objects
 //we can include jimsAccount because we 
 //only want to treat it as an Account object
 Account[] accounts = {bobsAccount, jimsAccount};
 
 //for each account in the array, display the balance
 for (Account a:accounts)
 {
   System.out.printf("The balance is %.2f%n", a.getBalance());
 }

 The output is:
 The balance is 60.00
 The balance is 65.05 

Everything appears to work as expected, here. But what if OverdraftAccount overrides the method getBalance()?  There is nothing to prevent it from doing something like this:

 public class OverdraftAccount extends Account {
 
   private double overdraftLimit;
   private double overdraftFee;
 
   //the rest of the class definition is not included
 
   public double getBalance()
   {
     return 25.00;
   }
 } 

If the example code above is executed again, the output will be different because the getBalance() behavior in the OverdraftAccount class is called for jimsAccount:

 The output is:
 The balance is 60.00
 The balance is 25.00 

Unfortunately, the subclass OverdraftAccount will never provide the correct balance because we have corrupted the behavior of the Account class through inheritance.

If you design a class to be used by other programmers, always consider the implications of any potential subclasses. This is the reason the String class cannot be extended. It's extremely important that programmers know that when they create a String object, it's always going to behave like a String.

How to Prevent Inheritance

To stop a class from being extended, the class declaration must explicitly say it cannot be inherited.

This is achieved by using the "final" keyword:

 public final class Account {
 
 } 

This means that the Account class cannot be a superclass, and the OverdraftAccount class can no longer be its subclass.

Sometimes, you may wish to limit only certain behaviors of a superclass to avoid corruption by a subclass. For example, OverdraftAccount still could be a subclass of Account, but it should be prevented from overriding the getBalance() method.

In this case use, the "final" keyword in the method declaration:

 public class Account {
 
   private double balance;
 
   //the rest of the class definition is not included
 
   public final double getBalance()
   {
     return this.balance;
   } 
 } 

Notice how the final keyword is not used in the class definition. Subclasses of Account can be created, but they can no longer override the getBalance() method.

Any code calling that method can be confident it will work as the original programmer intended.