Witscale Test Center

3.3 Class modifiers > 3.3.2 The final modifier


3.3.2 The final modifier

Quite obvious by its name, the final modifier mean you cannot change the context (class, method or variable) to which it is applied. For instance, if you apply it to a class, the class becomes ‘final’ or unchangeable. It means its behavior cannot be altered by subclassing it. In simple words, a final class cannot be subclassed. The String class in java.lang is a final class. Hence you cannot define subclass for it. For example, the code below will not compile.

 

class SpecialString extends java.lang.String {

}

 

The compiler would flag an error saying something like, “The type SpecialString cannot subclass the final class String

 

Why final class?

Declaring a class as final puts restriction on the class.  Let’s look at some situations in which you might want to use this restriction to your advantage:

Security reasons

A system’s security can be compromised by subclassing a critical class, modifying it, and then substituting the subclass for the original class. Such subclass may cause damage or extract sensitive information from the system. You can prevent this kind of intentional misuse by declaring the critical classes as final. This is one of the reasons why the String class in the java.lang package is a final class. The String class is so vital to the operation of the JVM that the Java system must ensure that whenever a method or objects uses a string, it gets an object of java.lang.String class and nothing else. Another example of a final class is the java.security.SecurityPermission class representing the Java security permissions. It is declared final to prevent anybody from extending it and compromising the Java security.

Design reasons

A class can also be declared as final when as a designer you are convinced that the class is complete in its implementation and there is no good reason why somebody should subclass it and extend it for any useful purpose.

Performance reasons

When a class is declared as final, the compiler/optimizer can make certain assumptions that can increase the performance. For example, if a class has heavily used utility methods like java.lang.Math class, declaring it as final will expand all its methods inline. In that case, the Java compiler puts the executable bytecode of the Math class directly [SK3] into any program that calls the method. This results in better performance.

 

We have discussed some situations where you should declare final classes. Similar to abstract classes, SCJP generally expects you to understand only the declaration rules for final classes, rather than the design situations where you should define a final class.

 

Declaration rules for final class

         Besides the fact that a final class cannot be subclassed, you need to follow certain rules when you declare a class as final: A class cannot to be final and abstract at the same time. This is reasonable as the abstract class implies that the implementation is deferred to subclasses, but if the class is also final then it cannot be subclassed, so the implementation could never be completed. A compile-time error occurs if a class is declared as both final and abstract.

         As a final class never has any subclasses, there is no question of overriding the methods of a final class. Thus, all the methods of a final class are unchangeable (final) by default. Method overriding is explained in detail in chapter 9. For now, remember that when you extend a class, the implementation of a method in superclass can be overridden (declared again) in the subclass by defining a method with same name and argument types.

         Since a final class is not extensible and forces every consumer to use the class as it is, you should only declare a class as final when you are sure about the reasons. (Security, design or performance reasons).