The finalize method, closeable interface, and try-with-resources statement (Java 7) - 1

"Hi, Amigo!"

"I just decided to discuss the finalize() method with you."

"If you remember, finalize() is a special method that is called by an object before
the garbage collector destroys it."

"This method's main purpose is to free up used external non-Java resources by closing files, I/O streams, and so on."

"Unfortunately, this method doesn't live up to our expectations. The Java virtual machine can postpone destroying an object, as well as calling the finalize method, as long as it wants. Moreover, it doesn't guarantee that this method will be called at all. There are loads of situations where it doesn't get called, all in the name of «optimization»."

"I've got two references for you:"

Joshua Bloch has written a good article about this method: link
I'll paraphrase a short excerpt:

  1. finalize() can only be used in two cases:
    1. For verifying or cleaning up resources with logging.
    2. When working with native code that is not critical to resource leaks.
  2. finalize() makes the GC 430 times slower at cleaning up objects
  3. finalize() might not be called
If I say in an interview that finalize is a harmful and dangerous crutch whose very existence is confusing, would I be right?

"Well, that made my day, Ellie."

"Java 7 has a new statement to replace the finalize method. It's called try-with-resources. It isn't really a replacement for finalize, rather it is an alternative approach."

"Is it like try-catch, but with resources?"

"It's almost like try-catch. The things is, unlike the finalize() method, the finally block in a try- catch-finally statement is always executed. Programmers have also used this technique when they've needed to free up resources, close threads, etc.

"Here's an example:"

InputStream is = null;
try
{
 is = new FileInputStream("c:/file.txt");
 is.read(…);
}
finally
{
 if (is != null)
 is.close();
}

"Regardless of whether the try block executed properly or there was an exception, the finally block will always be called, and it's possible to release occupied resources there."

"So, in Java 7, the decision was made to make this approach official, like so:"

try(InputStream is = new FileInputStream("c:/file.txt"))
{
 is.read(…);
}

"This special try statement is called try-with-resources (similar to how collections have an alternate for called foreach)."

"Notice that after the try there are parentheses where variables are declared and objects are created. These objects can be used inside the try block indicated by the curly brackets. When the try block is done being executed, regardless of whether it ended normally or there was an exception, the close() method will be called on any objects created inside the parentheses."

"How interesting! This notation is far more compact than the previous one. I'm not sure I understand it yet."

"It isn't as difficult as you think."

"So, can I specify the class of each object in the parentheses?"

"Yes, of course, otherwise the parentheses would be of little use."

"And if I need to call another method after exiting the try block, where do I put that?"

"Things are a bit more subtle here. Java 7 introduces the following interface:"

public interface AutoCloseable
{
 void close() throws Exception;
}

"Your class can implement this interface. And then you can use its objects inside a try-with-resources statement. Only such objects can be created inside the parentheses of a try-with-resources statement for «automatic closure»."

"In other words, I need to override the close method and write code in it to «clean up» my object, and I can't specify another method?"

"Yep. But you can specify several objects—just separate them with a semicolon:"

try(
InputStream is = new FileInputStream("c:/file.txt");
OutputStream os = new FileOutputStream("c:/output.txt")
)
{
 is.read(…);
 os.write(…);
}

"That's better, but not as cool as I'd hoped."

"It's not that bad. You'll get used to it. With time."