Final, Finally & Finalize In Java | 15+ Differences With Examples
In Java, understanding the differences between final, finally, and finalize is crucial as each serves a distinct purpose, despite their similar names. The final keyword is used primarily for constant values, preventing inheritance, and prohibiting method overriding. The finally block is related to exception handling, allowing code to execute after a try-catch block regardless of whether an exception occurs.
Meanwhile, finalize() is a method in the Object class, invoked by the garbage collector before an object is discarded. In this article, we will explore each in detail, examining their roles, usage, and how they contribute to Java programming best practices.
Key Difference Between final, finally, And finalize In Java
Given below are the key differences between final, finally, and finalize in Java programming:
Feature |
final |
finally |
finalize() |
Type |
Keyword |
Block |
Method |
Purpose |
Used to restrict class inheritance, prevent method overriding, and create constants |
Ensures that essential code runs after try-catch, regardless of exceptions |
Allows custom cleanup just before an object is garbage-collected |
Usage Context |
- Classes (final class ClassName {}): Prevents subclassing. - Methods (final void methodName() {}): Prevents overriding in subclasses. - Variables (final int VALUE = 10;): Creates a constant. |
Placed after try and catch blocks (try {...} catch {...} finally {...}) to ensure cleanup, especially for resources |
Defined in classes for cleanup purposes but rarely needed with modern resource management practices |
Execution Timing |
During compilation or runtime as it restricts inheritance and reassignment |
Executes immediately after try-catch, even if an exception is thrown |
Called by the garbage collector before object deletion |
Return Value |
Not applicable |
Not applicable |
Returns void (no return value) |
Common Usage |
- Constant values for readability and maintainability. - Security in code by restricting inheritance and modification. |
To release resources such as file streams or network connections in case of exceptions |
Rarely used today; try-with-resources or explicit resource handling is preferred |
Override Capability |
Cannot be overridden |
Not applicable |
Can be overridden but often discouraged due to unpredictable timing |
Memory Management |
Doesn't directly impact memory management but enforces structure |
Doesn't impact memory management |
May impact memory if misused; can slow down garbage collection |
Impact on Performance |
No direct impact; helps optimize by preventing overrides |
Minimal; typically used for resource cleanup |
Slows down garbage collection; not ideal for performance-sensitive code |
Impact on Inheritance |
Prevents inheritance (classes and methods) or reassignment (variables) |
Not relevant to inheritance |
Does not impact inheritance but is inherited from Object class |
Example |
java<br>final int CONSTANT = 10;<br> |
java<br>try { /* code */ } finally { /* cleanup code */ }<br> |
java<br>@Override protected void finalize() throws Throwable { /* cleanup code */ }<br> |
Associated Best Practices |
Use for immutability and secure class design |
Preferred for cleanup, but try-with-resources is often better |
Generally avoid; finalize() is deprecated since Java 9 |
Garbage Collection Impact |
No direct impact on garbage collection |
Not directly related to garbage collection |
Directly affects garbage collection timing if overridden |
Thread Safety |
Helps in creating immutable objects which support thread safety |
Typically thread-safe as it runs after try-catch |
Can create issues in multithreading; should not be relied upon for resource management |
Error Handling Relationship |
Unrelated to error handling |
Directly associated with error handling; ensures cleanup |
Not directly related to error handling but impacts cleanup if object has unreleased resources |
Notes |
- Ideal for constants, secure inheritance structure. - Use with caution in class design as it limits extensibility. |
- Use to ensure resource cleanup. - Works well with traditional try-catch but use try-with-resources where possible. |
- Deprecated and replaced by explicit resource management. - Avoid relying on it for critical cleanup. |
We will now discuss each one of them in detail, along with code examples in the sections ahead.
Explore this amazing course and master all the key concepts of Java programming effortlessly!
What Is final Keyword In Java?
The final keyword in Java is a modifier that can be applied to variables, methods, and classes to provide various types of restrictions. The final keyword's primary purpose is to enforce immutability and prevent changes in specific components of Java code.
Syntax Of final Keyword In Java
We can use the final keyword in Java in three different ways as follows:
1. Using final With Variables
A final variable in Java is a constant, meaning its value cannot be changed after it is initialized.
final dataType variableName = value;
Here:
- final: Modifier that makes the variable constant, prohibiting any reassignment after the initial assignment.
- dataType: Specifies the type of data (e.g., int, String) the variable will hold.
- variableName: The name of the variable(or identifier), which should follow standard naming conventions.
- =: Assignment operator used to set the initial and only value of the final variable.
- value: The fixed value assigned to the variable, which cannot be changed later in the code.
2. Using final With Methods
A final method cannot be overridden by subclasses. This ensures that the method's implementation remains unchanged in the inheritance hierarchy.
final returnType methodName(parameters) {
// method body
}
Here:
- final: Modifier that prevents the method from being overridden in any subclass.
- returnType: Specifies the type of value the method returns (e.g., int, void, String).
- methodName: The name of the method, following Java’s naming conventions.
- parameters: Input parameters for the method, enclosed in parentheses; they define the data the method can accept.
3. Using final With Classes
A final class cannot be subclassed, meaning it cannot be extended. This is useful when you want to prevent inheritance and ensure the class implementation remains unchanged.
final class ClassName {
// class body
}
Here:
- final: Modifier that prevents the class from being subclassed or extended by other classes.
- class: Keyword used to define a class in Java.
- ClassName: The name of the class, following Java's naming conventions.
Let’s now look at a code example to understand the working of final keyword in Java-
Code Example:
Output (Rename code file name to FinalDemo.java):
Max attempts allowed: 3
Explanation:
In the above code example-
- We start by defining a final class named FinalDemo. Declaring the class as final means it cannot be subclassed, which prevents any extension or modification to its structure in future classes.
- Inside the FinalDemo class, we declare a final variable called MAX_ATTEMPTS, initialized with the value 3. Since it's final, this variable can only be set once and cannot be changed later in the code.
- We define a method showMaxAttempts(), marked as final. Using final here ensures that this method cannot be overridden by any subclass, adding an additional layer of security to preserve the intended functionality.
- In the main method, we create an instance of FinalDemo called demo.
- We call demo.showMaxAttempts(), which outputs the value of MAX_ATTEMPTS to the console. This helps us see that the final variable holds the correct value.
- An important note: if we try to change the value of MAX_ATTEMPTS after it's initialized (like with demo.MAX_ATTEMPTS = 5;), it will cause a compilation error. Since MAX_ATTEMPTS is final, its value is locked and cannot be modified, preserving data integrity.
What Is finally Keyword In Java?
In Java, the finally keyword is used to define a block of code that will always execute after a try block, regardless of whether an exception was thrown or handled. The finally block is typically used for resource cleanup tasks, such as closing files or releasing database connections, ensuring that resources are freed even if an exception occurs.
Syntax Of finally Keyword In Java
try {
// Code that may throw an exception
} catch (ExceptionType e) {
// Exception handling code
} finally {
// Code that will always execute
}
Here:
- try: Block that contains code that may throw an exception. The code inside this block is monitored for exceptions.
- catch: Block that handles the exception if one is thrown in the try block. It catches specific exceptions (like ExceptionType) and provides a way to handle them.
- (ExceptionType e): Defines the type of exception that is caught (ExceptionType) and the variable (e) used to reference the caught exception.
- finally: Block that contains code that will always be executed, regardless of whether an exception occurred in the try block or not.
Code Example:
Output (Rename code file name to FinallyExample.java):
Inside try block
Exception caught: java.lang.ArithmeticException: / by zero
Finally block executed.
Explanation:
In the above code example-
- We define a class named FinallyExample, with the main method as the entry point of the program.
- Inside the main method, we begin with a try block. This block contains code that could potentially throw an exception.
- In our case, we attempt to divide 10 by 0, which is not allowed in Java and will throw an ArithmeticException.
- When the exception is thrown, the catch block immediately handles it. Here, we catch the ArithmeticException and print a message, "Exception caught," followed by the exception details. This ensures that our program handles the error gracefully without crashing.
- Following the try and catch blocks, we have a finally block. Regardless of whether an exception occurs or not, the finally block will execute, ensuring that any essential cleanup or final actions are taken. In this example, it prints "Finally block executed."
- The key takeaway is that the finally block provides a way to run important code no matter the outcome of the try and catch blocks, making it reliable for cleanup operations or mandatory statements.
What Is finalize Keyword In Java?
The finalize keyword in Java is used to define a method, finalize(), that is called by the garbage collector before an object is destroyed. The purpose of the finalize() method is to provide a final opportunity for an object to perform cleanup operations before it is removed from memory. This method belongs to the Object class and can be overridden in custom classes to release resources or handle cleanup tasks.
Syntax Of finalize Keyword In Java
protected void finalize() throws Throwable {
// Cleanup code
}
Here:
- protected: Access modifier that makes the finalize() method accessible within the same package and by subclasses.
- void: Specifies that the finalize() method does not return any value.
- finalize(): The method name, which is a special method called by the garbage collector before an object is removed from memory.
- throws Throwable: The parentheses indicate that the method can throw exceptions (in this case, Throwable) during its execution, which must be handled or declared.
Code Example:
Output (Rename code file name to FinalizeExample.java):
Object created.
End of main method.
finalize() method called for cleanup.
Explanation:
In the above code example-
- We define a class named FinalizeExample with a constructor that prints "Object created." whenever an instance of this class is created, allowing us to observe object creation.
- Inside this class, we override the finalize() method. The finalize() method is called by the garbage collector when it's about to reclaim the object's memory. Here, we include a print statement in finalize() to indicate when cleanup actions are performed.
- In the finalize() method, we use a try-finally block. This ensures that our custom cleanup code executes first, followed by the super.finalize() call, which invokes the superclass's finalize() method to complete any further necessary cleanup.
- In the main method, we create an instance of FinalizeExample, which triggers the constructor and displays "Object created."
- We then set example to null, effectively dereferencing it so that the object becomes eligible for garbage collection.
- To prompt garbage collection, we call System.gc(). This request isn't guaranteed to trigger garbage collection immediately, but if it does, finalize() will be called on the object marked for cleanup.
- Finally, we print "End of main method." to indicate the main method's end. This allows us to see that even as the program finishes, finalize() may still execute if garbage collection occurs, ensuring our cleanup actions are complete.
Sharpen your coding skills with Unstop's 100-Day Coding Sprint and compete now for a top spot on the leaderboard!
When To Use Which Keyword In Java?
When working with Java, knowing when to use each of the keywords final, finally, and finalize helps ensure your code is efficient, maintainable, and optimized for resource management. Here’s a guide on when to use each:
When To Use final Keyword In Java?
The final keyword is best used to enforce immutability, control inheritance, and secure methods or variables against modification.
- For Constants: Use final with variables to create constants, ensuring they are immutable and can’t be changed after initialization. For Example-
final int MAX_CONNECTIONS = 10;
- To Prevent Inheritance: Use final with a class when you don’t want it to be subclassed. This is useful for classes like utility classes or critical classes that should not be modified by subclasses. For Example-
public final class DatabaseUtils { ... }
- To Prevent Method Overriding: Use final with methods when you need to secure their behavior and ensure subclasses can’t override them, preserving core functionality. For Example-
public final void displayDetails() { ... }
- For Immutable Objects: Use final with object references to ensure the reference cannot point to a different object after assignment, promoting immutability in your code.
When To Use finally Keyword In Java?
The finally block is ideal for resource management and guaranteeing the execution of critical code after a try-catch block.
- For Resource Cleanup: Use finally to ensure that resources (e.g., files, database connections) are properly closed or released, regardless of whether an exception is thrown. For Example-
try {
FileInputStream file = new FileInputStream("file.txt");
// Code to process file
} finally {
file.close(); // Ensures file is closed
}
- To Ensure Code Execution: Use finally when you have code that must execute even if an exception is thrown, such as logging, releasing locks, or resetting values.
When To Use finalize Keyword In Java?
The finalize keyword is used to define a finalize() method for cleanup before garbage collection, though it’s deprecated due to unreliable behavior and performance issues. Alternatives like try-with-resources are recommended instead.
- For Last-Resort Cleanup: Use finalize() only if absolutely necessary for non-Java resources, such as native code objects, where other cleanup methods are infeasible. For Example-
@Override
protected void finalize() throws Throwable {
// Last-minute cleanup code
}
- When No Other Options Are Available: Since finalize() can be unpredictable, it’s best avoided unless there’s no alternative. It can be useful in legacy systems, but using try-with-resources or finally blocks is strongly preferred.
To Summarize
Keyword |
Best Used For |
Examples |
final |
Constants, securing classes/methods, immutability |
Constants, utility classes, critical methods |
finally |
Resource management, guaranteed execution |
File or database cleanup, logging, releasing resources |
finalize |
Deprecated cleanup before garbage collection |
Rare cases of unmanaged resources, legacy systems |
Are you looking for someone to answer all your programming-related queries? Let's find the perfect mentor here.
Conclusion
Understanding the differences between final, finally, and finalize in Java is crucial for writing clean, maintainable, and efficient code. Each keyword serves a unique purpose:
- The final ensures immutability, prevents modifications, and secures classes, methods, or variables against unwanted changes.
- The finally guarantees that critical code, such as resource cleanup, is executed regardless of exceptions, ensuring reliability in exception handling.
- The finalize, though deprecated, was historically used for last-minute object cleanup before garbage collection, but modern alternatives like try-with-resources are now preferred.
By using these keywords appropriately, we can enhance the clarity, performance, and safety of our Java programs, aligning with best practices for object-oriented programming.
Frequently Asked Questions
Q. What happens if I try to modify a final variable in Java?
Attempting to modify a final variable after it has been initialized results in a compilation error. final variables can be assigned a value only once, making them immutable. If the final variable is a reference to an object, you cannot reassign the reference to point to a different object, although the object's internal state may still be altered.
Q. Can I use the finally block without a try block in Java?
No, a finally block cannot exist without a try block. It is designed to follow a try or try-catch structure, where it provides a place for code that must run regardless of whether an exception is thrown. This structure helps ensure that critical cleanup or release of resources (like closing files or database connections) is always performed.
Q. Why is finalize() deprecated, and what should I use instead?
finalize() is deprecated because it has unpredictable execution timing and can lead to performance issues, as the garbage collector may not call it promptly. In place of finalize(), Java provides more reliable alternatives like try-with-resources (Java 7 and later) for automatic resource management or explicitly closing resources in finally blocks. These approaches offer more control and ensure that resources are released as expected.
Q. Can a final method be overloaded in Java?
Yes, a final method can be overloaded. Overloading is based on different parameter lists and does not involve overriding the method’s existing functionality. A final method, however, cannot be overridden in any subclass, as marking it final prevents subclasses from altering its behavior.
Q. What is the purpose of finally when we use try-with-resources?
With try-with-resources, resources are automatically closed at the end of the try block, reducing the need for a finally block specifically for cleanup. However, finally can still be useful for other actions that must be performed regardless of whether an exception occurs, such as logging or resetting variables, even though resources are automatically handled.
Q. Can a final class in Java implement interfaces?
Yes, a final class can implement one or more interfaces. Declaring a class as final only prevents it from being extended by other classes; it does not restrict it from implementing interfaces. For example, public final class MyFinalClass implements MyInterface { ... } is valid.
Q. What are some best practices for using final, finally, and finalize?
Some of the best practices for using final, finally, and finalize are as follows:
- final: Use final for variables that should not change, such as constants, and to secure methods or classes where modifications could compromise functionality.
- finally: Reserve finally for critical cleanup actions, like closing resources, especially if using older versions of Java that lack try-with-resources.
- finalize: Avoid finalize() in favor of more reliable resource management practices; it is deprecated and may lead to unpredictable behavior.
With this, we conclude our discussion on the key differences between final, finally, and finalize. Here are a few other topics that you might be interested in reading:
- 15 Popular JAVA Frameworks Use In 2023
- What Is Scalability Testing? How Do You Test Application Scalability?
- Top 50+ Java Collections Interview Questions
- 10 Best Books On Java In 2024 For Successful Coders
- Difference Between Java And JavaScript Explained In Detail
- Top 15+ Difference Between C++ And Java Explained! (+Similarities)