Example 1: How to Use a Final Class?
Using a final class in Java is similar to using any other class, but with the understanding that it cannot be extended. Here's a practical example to illustrate how you might utilize a final class in a real-world scenario:
Suppose you have a final class named Calculator that provides basic arithmetic operations. Since you want to ensure that the behavior of the calculator is consistent and secure without any subclass altering its functionality, you make it final.
public final class Calculator {
// Method to add two numbers
public int add(int num1, int num2) {
return num1 + num2;
}
// Method to subtract two numbers
public int subtract(int num1, int num2) {
return num1 - num2;
}
// Method to multiply two numbers
public int multiply(int num1, int num2) {
return num1 * num2;
}
// Method to divide two numbers
public int divide(int num1, int num2) {
if (num2 == 0) {
throw new IllegalArgumentException("Cannot divide by zero.");
}
return num1 / num2;
}
}
How to Use This Class
-
Instantiation: You create an object of the Calculator class.
- Operation: You call its methods to perform calculations.
Java
public class Main {
public static final class Calculator {
// Method to add two numbers
public int add(int num1, int num2) {
return num1 + num2;
}
// Method to subtract two numbers
public int subtract(int num1, int num2) {
return num1 - num2;
}
// Method to multiply two numbers
public int multiply(int num1, int num2) {
return num1 * num2;
}
// Method to divide two numbers
public int divide(int num1, int num2) {
if (num2 == 0) {
throw new IllegalArgumentException("Cannot divide by zero.");
}
return num1 / num2;
}
}
public static void main(String[] args) {
Calculator myCalc = new Calculator();
int sum = myCalc.add(5, 3);
int difference = myCalc.subtract(5, 3);
int product = myCalc.multiply(5, 3);
int quotient = myCalc.divide(5, 3);
System.out.println("Sum: " + sum);
System.out.println("Difference: " + difference);
System.out.println("Product: " + product);
System.out.println("Quotient: " + quotient);
}
}

You can also try this code with Online Java Compiler
Run Code
Output
Sum: 8
Difference: 2
Product: 15
Quotient: 1
In this example, the Calculator class functions purely to provide arithmetic results. Making it final ensures that no other class can modify its methods, which is crucial for maintaining the calculator’s reliability.
Example 2: What Happens if We Try to Inherit from a Final Class?
In Java, attempting to inherit from a final class will result in a compile-time error. This is because a final class is designed to be a terminal class in the inheritance chain, meaning it cannot be subclassed. This restriction ensures that the original class's behavior remains unchanged and secure throughout its use in any Java application.
Let's look at an example where you might unintentially try to extend a final class:
Assume we have the Calculator class from the previous example declared as final.
public final class Calculator {
public int add(int num1, int num2) {
return num1 + num2;
}
}
Now, suppose you try to create a new class called AdvancedCalculator that extends Calculator to add more features like calculating the square root or power of numbers:
public class AdvancedCalculator extends Calculator { // This line will cause a compile error
public double sqrt(int number) {
return Math.sqrt(number);
}
public int power(int base, int exponent) {
return (int) Math.pow(base, exponent);
}
}
When you try to compile this code, the Java compiler will stop you right there with an error message similar to:
error: cannot inherit from final Calculator
Why Does Java Prevent Inheritance from Final Classes?
The main reason is to maintain the integrity and security of the class’s intended functionality. By preventing other classes from inheriting from a final class, Java ensures that the class’s methods and properties cannot be altered or extended in potentially harmful ways. This is particularly important for classes that perform critical functions or handle sensitive data.
This design choice by Java helps in creating robust and secure applications, where certain components are kept stable and unchangeable.
Advantage of the Final Class
-
Security: By marking a class as final, you prevent other developers from altering its implementation by extending it. This is crucial for classes that implement security-sensitive functionality. If you have a class that manages authentication, you wouldn’t want its methods overridden in a way that could compromise security.
-
Simplicity: Final classes are easier to understand and maintain because they are not burdened with the complexity of subclasses modifying their behavior. There’s no need to consider the effects of inheritance when updating or debugging the class, which simplifies development tasks.
-
Creation of Immutable Objects: Classes designed as immutable (whose states cannot be changed once constructed) can be made final to enforce this property. For example, the String class in Java is final and immutable, meaning you can rely on its value never changing once it’s been initialized.
-
Performance Optimization: Java compilers can make certain optimizations for final classes. Knowing that these classes cannot be extended, the compiler can perform method invocations faster, sometimes using inline expansions. This is because there's no need to look up methods in a dynamic dispatch table.
-
Stable Software Components: When designing large systems, using final classes helps ensure that certain components remain stable as the software evolves. This stability can make it easier to expand or modify the system without worrying about changes to fundamental behaviors dictated by these classes.
- Encourages Composition Over Inheritance: Java’s use of the final keyword encourages developers to use composition instead of inheritance when designing their systems. Composition involves creating systems by combining objects, which is often more flexible than inheritance. This leads to better separation of concerns and more modular code.
Frequently Asked Questions
Can a final class include non-final methods?
Yes, a final class can still have non-final methods. The final designation prevents the class from being extended, but individual methods within the class can still be overridden if they are inherited from a non-final superclass.
Is it possible to declare a final class as abstract?
No, declaring a final class as abstract is not possible in Java. Abstract classes are meant to be extended to complete their implementation, while final classes cannot be extended. Thus, these two keywords are mutually exclusive.
How does using a final class affect unit testing?
Using final classes can sometimes make unit testing challenging because it prevents mocking classes. If you need to test code that uses final classes, you might have to use real instances of those classes, which can complicate tests or reduce their flexibility.
Conclusion
In this article, we have learned about the concept of final classes in Java and their practical applications. We explored how to declare and use final classes with examples, understood the implications of trying to inherit from such a class, and discussed the advantages that make final classes beneficial in certain programming scenarios. Through these discussions, it's clear that final classes play a vital role in creating secure, stable, and efficient Java applications by ensuring that certain classes remain unchangeable and free from unwanted modifications through inheritance.
You can refer to our guided paths on the Coding Ninjas. You can check our course to learn more about DSA, DBMS, Competitive Programming, Python, Java, JavaScript, etc. Also, check out some of the Guided Paths on topics such as Data Structure andAlgorithms, Competitive Programming, Operating Systems, Computer Networks, DBMS, System Design, etc., as well as some Contests, Test Series, and Interview Experiences curated by top Industry Experts.