Every time a program opens a resource, such as a file or network connection, it is important to free the resource once you are done using it. Similar caution should be taken if any exception were to be thrown during operations on such resources. One could argue that the FileInputStream
has a finalizer that invokes the close()
method on a garbage collection event; however, since we can’t be sure when a garbage collection cycle will start, the input stream can consume computer resources for an indefinite period of time. The resource must be closed in a finally
section of a try-catch block:
private static void printFileJava6() throws IOException {
FileInputStream input;
try {
input = new FileInputStream("file.txt");
int data = input.read();
while (data != -1){
System.out.print((char) data);
data = input.read();
}
} finally {
if (input != null) {
input.close();
}
}
}
Since Java 7 there is a really useful and neat statement introduced in Java 7 particularly for this case, called try-with-resources:
private static void printFileJava7() throws IOException {
try (FileInputStream input = new FileInputStream("file.txt")) {
int data = input.read();
while (data != -1){
System.out.print((char) data);
data = input.read();
}
}
}
The try-with-resources statement can be used with any object that implements the Closeable
or AutoCloseable
interface. It ensures that each resource is closed by the end of the statement. The difference between the two interfaces is, that the close()
method of Closeable
throws an IOException
which has to be handled in some way.
In cases where the resource has already been opened but should be safely closed after use, one can assign it to a local variable inside the try-with-resources
private static void printFileJava7(InputStream extResource) throws IOException {
try (InputStream input = extResource) {
... //access resource
}
}
The local resource variable created in the try-with-resources constructor is effectively final.