finalize
Method
The finalize()
method of a Java class is useful during garbage collection. Java does automatic garbage collection and periodically reclaims memory occupied by objects that are no longer referenced by any other object. If an object utilizes a resource other than memory, such as a file or a handle to another object that uses system resources then it is important that the resource should be freed before the object is reclaimed and recycled by garbage collector. A finalizer (finalize()
method) added to any class is called before the garbage collector sweeps away the object. However, in practice we should not rely on the finalize()
method for short supply resources because finalize()
only guarantees that it will be called during garbage collection but when will garbage collector run, it depends upon system. So, if a resource needs to be closed as soon as you are done using it, you need to close it manually. Supply a method of your own for what needs to be immediately closed after use.
The signature of finalize()
method must be as follows:
protected void finalize () throws throwable
Following is a trivial example demonstrating finalize()
method. Class OpenFile
opens a file when an instance is created.
class OpenFile { FileInputStream aFile = null; OpenFile(String filename) { try { aFile = new FileInputStream(filename); } catch (java.io.FileNotFoundException e) { System.err.println("Could not open file " + filename); } } }
By using finalize()
, an instance of OpenFile
can close the file as follows.
protected void finalize () throws Throwable { if (aFile != null) { aFile.close(); aFile = null; } }
The finalize()
method is declared in the java.lang.Object
class. Thus when you write a finalize()
method for your class you are overriding the one in your superclass. If your class's superclass has a finalize()
method, then your class's finalize()
method should call the superclass's finalize()
method after it has performed its clean up duties. This cleans up any resources the object may have unknowingly obtained through methods inherited from the superclass.
The most important thing we should keep in mind while using finalizers is:
After a finalizer is invoked, objects are not freed right away. This is because a finalizer method can resurrect an object by storing the this
pointer somewhere so that the object once again has references. Thus, after finalize()
is called, the garbage collector must once again determine that the object is unreferenced before it can garbage-collect it. However, even if an object is resurrected, the finalizer method is never invoked more than once. Resurrecting an object is never a useful thing to do -- just a strange quirk of object finalization. As of Java 1.2, the java.lang.ref.PhantomReference
class can implement an alternative to finalization that does not allow resurrection.
finally
Block
Java's finally
block is useful in exception handling and always used in conjunction with try
block. There should at least be one try
block that finally
block can be associated to. The try
encloses a block of code in which exception may occur. When a piece of code throws an exception, it stops processing the remaining code in try
block and transfers the control to an appropriate catch
block. There can be more than one catch
block associated to a single try
block but only one catch
block is processed at a time. Also note that the catch
blocks immediately follow the try
block.
So, exceptions are thrown from try
block and caught by catch
block then why finally
needed and what is its purpose? Let us see that. Upon occurrence of an exception a method may decide to exit, which could be problematic, in case, the method has acquired some local resource that only it knows about and if that resource must be cleaned up before exiting the method. To tackle this problem Java provides finally
clause. However, you can place the clean up code in catch
blocks, but exception handlers (catch
blocks) are a poor place to clean up after the code in the try
block because each handler then requires its own copy of the clean up code. If, for example, you allocated a network resource or opened a file somewhere in the try
block, each exception handler would have to close the file or release the resource. That would definitely lead to a lot of redundant code. To get rid of this problem, Java offers the finally
block.
Piece of code contained by finally
block is executed at some point after the try
block, whether an exception is thrown or not. Even if there is a return
statement in the try
block, the finally
block gets executed right after the return
statement is encountered, and before the return
gets executed.
If the try
block gets executed with no exceptions, the finally
block is executed immediately after the try
block completes. If there was an exception thrown, the finally
block gets executed immediately after the proper catch
block completes. The finally
block will not be executed if exit()
is called before finally
block is reached. The exit()
call will shutdown the JVM, so no subsequent line of code will be run.
Remember, finally
clauses are optional. If you don't code one, your program will compile and run just fine. You need not to code finally
block if you have no resources to clean up. There will always be only one finally
clause associated to a try
block. In case of multiple try
blocks you can have multiple finally
clauses ensuring their proper association to try
statements.
final
Keyword
Most of the times you see Java's final
keyword is used to define constants but there are other uses of final
as well. Following is a list of uses of final
keyword.
Using final
to define constants: If you want to make a local variable, class variable (static
field), or instance variable (non-static filed) constant, declare it final
. A final variable may only be assigned to once and its value will not change and can help avoid programming errors.
Once a final
variable has been assigned, it always contains the same value. If a final
variable holds a reference to an object, then the state of the object may be changed by operations on the object, but the variable will always refer to the same object.
This also applies to arrays, because arrays are objects; if a final
variable holds a reference to an array, then the components of the array may be changed by operations on the array, but the variable will always refer to the same array.
This applies also to arrays, because arrays are objects; if a final
variable holds a reference to an array, then the components of the array may be changed by operations on the array, but the variable will always refer to the same array.
Using final
to prevent inheritance: If you find a class's definition is complete and you don't want it to be sub-classed, declare it final
. A final
class cannot be inherited, therefore, it will be a compile-time error if the name of a final
class appears in the extends
clause of another class declaration; this implies that a final
class cannot have any subclasses.
It is a compile-time error if a class is declared both final
and abstract
, because the implementation of such a class could never be completed.
Because a final
class never has any subclasses, the methods of a final
class are never overridden
Using final
to prevent overriding: When a class is extended by other classes, its methods can be overridden for reuse. There may be circumstances when you want to prevent a particular method from being overridden, in that case, declare that method final
. Methods declared as final
cannot be overridden.
Using final
for method arguments: Formal parameters of a method can be declared final
to prevent them from accidental changes during the execution of method body.
Hope you have enjoyed reading about finalize
method, finally
block and final
keyword. Please do write us if you have any suggestion/comment or come across any error on this page. Thanks for reading!
Share this page on WhatsApp