Java: final, finally and finalize

One of the most popular Java interview “screener” questions is often, “What is the difference between final, finally and finalize?” In fact, it occurs so much that one should probably have the answer memorized. But knowing when to use these features is better than just knowing what they mean.

The final keyword – classes and methods

When used on a class, final prevents the class from being extended. Similarly, when final is used on a method, that method cannot be overridden in any subclass.

This is mainly done for reasons of security and consistency: If you have a class whose methods you count on to provide predictable results, you may want to prevent that class from being extended so that someone cannot substitute a subclass that behaves differently to a consumer that expects your original class. The same may go for certain methods on a class.

But generally, you should not be marking classes/methods as final unless you have a compelling argument for it. The reason is that using final may unnecessarily constrain the design and hamper future developers who may have a legitimate reason for wanting to extend your class. Though I prefer composition over inheritance, it’s not a choice I would want to force on everyone else, nor do I believe it’s always the right choice.

In particular, you should not be marking classes/methods as final just for some perceived performance benefit. In many cases you won’t gain a thing performance wise, but will be unnecessarily be constraining your design.

One reason you shouldn’t refrain from marking a method as final is for mockability; mocking frameworks like JMockit allow you to easily mock out final methods, so don’t let that affect your design decisions.

The final keyword – variables

When used on variables, final essentially means that the variable can only be assigned once. For class/static members, this is when the class is loaded; for instance members, this is when an instance of the class is created; for local variables, it is usually when the variable is declared. Method parameters can also be declared as final.

As opposed to the use of final on classes/methods, I usually like using final for most variables, as it can decrease the complexity of code by decreasing the chances for state changes. Once you know that a local variable is final, if it’s primitive, you can be sure its value won’t change; if it’s an object, you can be sure you’ll always be dealing with the same object.

Furthermore, the use of final on member variables ensures that you know they’ll be assigned once and only once: At object creation.

Some people may think that the use of final variables is superfluous, but I think it’s a good defensive programming technique. This article sums up my viewpoints nicely.

finally

As opposed to the final keyword, which is completely optional and not strictly necessary to use, you should almost always be using the finally keyword in Java when dealing with closeable resources. (This is true before Java 7, as Java 7 introduces some nice syntactic sugar that can remove the need to use finally)

Here is a contrived example:

InputStream inputStream = null;
try {
  inputStream = new FileInputStream(new File("TEST.XML"));
  final int read = inputStream.read();
  // Do other stuff with the stream...
} finally {
  if (null != inputStream) {
    inputStream.close();
  }
}

In this example, we initialize the inputStream within a try block. If anything goes wrong with reading from the stream, an exception will be thrown (which we don’t handle here, for brevity) but before it is allowed to propagate, the code within the finally block will be executed, ensuring that if the stream has been opened, it will be closed. This will prevent a resource leak from happening.

Here is how that code could also look in Java 7:

try (final InputStream inputStream = new FileInputStream(new File("TEST.XML"))) {
  final int read = inputStream.read();
  // Do other stuff with the stream...
}

As you can see, the amount of “boilerplate” is reduced as we don’t need to have an explicit finally block anymore. This is known as a “try-with-resources” statement, where an object that implements Closeable/AutoCloseable is declared and initialized with the try statement and automatically closed no matter what the outcome of the statements within the try block. I would suggest using this unless your code needs to be JDK 6 compatible.

finalize()

As opposed to final, which you may use and finally, which you will certainly have to use in JDK 6 and below, you will almost never need to implement or override Object.finalize().

The finalize() method is called by the garbage collector (GC) determines that there is no longer anyway for the object to accessed; this means the object is eligible for finalization, which means the GC can begin the process of making the object finalizable, finalized and then reclaimed. Generally any Object that does not have a Strong reference is eligible.

There is generally no need to override the default finalize() method; if your class opens resources then it should be responsible for properly closing/releasing them by using try-catch-finally as outlined above, or you should make your class implement Closeable so that clients/callers of your class can ensure its proper closure.

You could, in theory, use finalize() as a “safety net” of sorts to mitigate the effects of bad clients/callers not calling close() on your class by ensuring that internal resources are closed/released in finalize() but you should never rely on this.

Additionally, if you are overriding finalize() you must take care to ensure that you don’t “leak” a reference to the object to the “outside world”, or else this may prevent the object from being garbage collected, resulting in a potential memory leak! (i.e. don’t pass a reference to this to any external objects during finalize())

In general, if you are going to implement/override finalize(), you should have a very specific reason and be very careful in how you do so.

The final word

I hope you enjoyed this summary of final, finally and finalize(). Learning these concepts is pretty fundamental to having a good understanding of Java as a whole.

Comments for this entry are closed

But feel free to indulge in some introspective thought.