Java > Object-Oriented Programming (OOP) > Inheritance > Final Keyword (Methods, Classes, Variables)
Final Keyword: Preventing Inheritance and Modification
This snippet demonstrates the use of the final
keyword in Java to prevent inheritance, method overriding, and variable modification. Understanding final
is crucial for designing robust and maintainable object-oriented systems.
Base Class with Final Method and Final Class
This code illustrates three uses of the final
keyword:
1. Final Class: The FinalClass
is declared as final
. This prevents any other class from inheriting from it. Attempting to create a SubClass
extending FinalClass
will result in a compile-time error.
2. Final Method: The finalMethod
within FinalClass
and RegularClass
is declared as final
. This prevents subclasses from overriding the method. Attempting to override finalMethod
in a subclass will result in a compile-time error.
3. Final Variable: The finalVariable
within FinalClass
is declared as final
. This means its value cannot be changed after it's initialized. Similarly, localFinalVariable
in main
is a final local variable.
The commented-out sections show what would cause compilation errors.
final class FinalClass {
private final int finalVariable;
public FinalClass(int finalVariable) {
this.finalVariable = finalVariable;
}
public final void finalMethod() {
System.out.println("This is a final method. Cannot be overridden.");
}
public int getFinalVariable() {
return finalVariable;
}
public void display() {
System.out.println("Final Class Display: " + finalVariable);
}
}
// This class would cause a compilation error because FinalClass is final
// class SubClass extends FinalClass {}
class RegularClass {
public final void finalMethod() {
System.out.println("This is a final method in RegularClass");
}
}
class SubRegularClass extends RegularClass {
//Trying to override finalMethod causes a compilation error
// @Override
// public void finalMethod() {
// System.out.println("Attempting to override final method");
// }
}
public class FinalExample {
public static void main(String[] args) {
final int localFinalVariable = 10; // Local final variable
// localFinalVariable = 20; // Error: Cannot assign a value to final variable 'localFinalVariable'
FinalClass finalObj = new FinalClass(5);
finalObj.finalMethod();
System.out.println("Final Variable Value: " + finalObj.getFinalVariable());
RegularClass regularObj = new RegularClass();
regularObj.finalMethod();
SubRegularClass subRegularObj = new SubRegularClass();
subRegularObj.finalMethod();
}
}
Concepts Behind the Snippet
The final
keyword is a non-access modifier that signifies immutability or prevention of extension. It's a fundamental concept in Java for controlling inheritance and ensuring data integrity.
* Final Class: Guarantees that the class's implementation will remain unchanged and prevents unintended behavior through inheritance.
* Final Method: Ensures that the method's behavior remains consistent across all subclasses. It also allows the compiler to perform certain optimizations.
* Final Variable: Ensures that the variable's value remains constant after initialization. This is crucial for representing constants and immutable data.
Real-Life Use Case
Consider a scenario where you're building a security library. You might have a PasswordHasher
class with a hashPassword
method. To ensure consistent hashing algorithms across the system and prevent subclasses from altering the hashing process, you would declare both the class and the hashPassword
method as final
. Similarly, API keys are usually defined as final variables.
final class PasswordHasher {
private final String salt;
public PasswordHasher(String salt) {
this.salt = salt;
}
public final String hashPassword(String password) {
// Hashing logic here, utilizing the final salt
return password + salt; // Simplified example
}
}
Best Practices
Here are some best practices when using the final
keyword:
* Use final
for classes that represent immutable concepts or entities.
* Use final
for methods when you want to guarantee that the method's implementation is not changed by subclasses.
* Use final
for variables that should represent constants or that should only be assigned once.
* Consider the impact on extensibility when making a class or method final
. It prevents further modification through inheritance or overriding.
* Use meaningful names for final variables, especially if they represent constants, to improve code readability (e.g., MAX_RETRIES
instead of just max
).
Interview Tip
Be prepared to explain the different uses of the final
keyword and the reasons behind each use case. Common interview questions include scenarios where you would use final
and the impact of using final
on inheritance and method overriding. For example: 'Explain the difference between finally, finalize, and final keywords'. Also, consider potential design implications when declaring a class final versus leaving it open for extension.
When to Use Them
* Final Class: Use when you want to prevent inheritance. This is useful for immutable classes or classes where the implementation is critical and should not be changed. * Final Method: Use when you want to prevent overriding. This is useful when you want to ensure that a method's behavior remains consistent across all subclasses. Use with caution, as it reduces flexibility. * Final Variable: Use when you want to ensure that a variable's value cannot be changed after initialization. This is useful for constants, immutable objects, and values that should only be assigned once.
Memory Footprint
The final
keyword itself doesn't directly impact memory footprint at runtime. However, the compiler can perform optimizations when it knows that a variable, method, or class is final
. For instance, it might be able to inline final
methods, reducing the overhead of method calls. For final variables, the compiler can sometimes replace the variable with its constant value directly, optimizing the code.
Alternatives
Instead of using final
to prevent inheritance, consider using composition. Instead of inheriting from a class, you can include an instance of that class as a member variable. This allows you to reuse the functionality of the other class without inheriting its interface. For preventing method overriding, consider making methods private
if they are only used within the class itself. Private methods are implicitly final. Note that in modern Java, records provide an alternative for creating immutable data classes more concisely.
Pros
* Increased Security: Prevents unauthorized modification of critical classes and methods. * Improved Performance: Allows the compiler to perform optimizations. * Enhanced Code Readability: Clearly indicates which parts of the code are intended to be immutable or non-extensible. * Guaranteed Consistency: Ensures that certain behaviors remain consistent across all parts of the system.
Cons
* Reduced Flexibility: Limits the ability to extend or modify existing code. Overuse can lead to rigid designs. * Potential for Code Duplication: May require duplicating code if inheritance is prevented and functionality needs to be reused in different contexts. Carefully evaluate the trade-offs between flexibility and immutability.
FAQ
-
What is the difference between
final
,finally
, andfinalize
?
final
is a keyword used to define entities that cannot be changed (classes, methods, variables).finally
is a block of code that is always executed after atry
block, regardless of whether an exception was thrown.finalize
is a method called by the garbage collector on an object when garbage collection determines that there are no more references to the object. -
Can a
final
variable be initialized later?
Afinal
variable must be initialized exactly once. It can be initialized either at the time of declaration or within the constructor of the class. -
Can a
final
method be overloaded?
Yes, afinal
method can be overloaded. Overloading refers to defining multiple methods with the same name but different parameters.final
only prevents overriding (redefining the method with the same signature in a subclass).