I\'m in the process of learning Java and I cannot find any good explanation on the implements Closeable
and the implements AutoCloseable
interfaces
Here is the small example
public class TryWithResource {
public static void main(String[] args) {
try (TestMe r = new TestMe()) {
r.generalTest();
} catch(Exception e) {
System.out.println("From Exception Block");
} finally {
System.out.println("From Final Block");
}
}
}
public class TestMe implements AutoCloseable {
@Override
public void close() throws Exception {
System.out.println(" From Close - AutoCloseable ");
}
public void generalTest() {
System.out.println(" GeneralTest ");
}
}
Here is the output:
GeneralTest
From Close - AutoCloseable
From Final Block
AutoCloseable (introduced in Java 7) makes it possible to use the try-with-resources idiom:
public class MyResource implements AutoCloseable {
public void close() throws Exception {
System.out.println("Closing!");
}
}
Now you can say:
try (MyResource res = new MyResource()) {
// use resource here
}
and JVM will call close()
automatically for you.
Closeable is an older interface. For some reason To preserve backward compatibility, language designers decided to create a separate one. This allows not only all Closeable
classes (like streams throwing IOException
) to be used in try-with-resources, but also allows throwing more general checked exceptions from close()
.
When in doubt, use AutoCloseable
, users of your class will be grateful.
Recently I have read a Java SE 8 Programmer Guide ii Book.
I found something about the difference between AutoCloseable
vs Closeable
.
The AutoCloseable
interface was introduced in Java 7. Before that, another interface
existed called Closeable
. It was similar to what the language designers wanted, with the
following exceptions:
Closeable
restricts the type of exception thrown to IOException
.Closeable
requires implementations to be idempotent.The language designers emphasize backward compatibility. Since changing the existing
interface was undesirable, they made a new one called AutoCloseable
. This new
interface is less strict than Closeable
. Since Closeable
meets the requirements for
AutoCloseable
, it started implementing AutoCloseable
when the latter was introduced.
It seems to me that you are not very familiar with interfaces. In the code you have posted, you don't need to implement AutoCloseable.
You only have to (or should) implement Closeable or AutoCloseable if you are about to implement your own PrintWriter
, which handles files or any other resources which needs to be closed.
In your implementation, it is enough to call pw.close()
. You should do this in a finally block:
PrintWriter pw = null;
try {
File file = new File("C:\\test.txt");
pw = new PrintWriter(file);
} catch (IOException e) {
System.out.println("bad things happen");
} finally {
if (pw != null) {
try {
pw.close();
} catch (IOException e) {
}
}
}
The code above is Java 6 related. In Java 7 this can be done more elegantly (see this answer).
The try-with-resources
Statement.
The try-with-resources statement
is a try
statement that declares one or more resources. A resource
is an object that must be closed after the program is finished with it. The try-with-resources statement
ensures that each resource is closed at the end of the statement. Any object that implements java.lang.AutoCloseable
, which includes all objects which implement java.io.Closeable
, can be used as a resource.
The following example reads the first line from a file. It uses an instance of BufferedReader
to read data from the file. BufferedReader
is a resource that must be closed after the program is finished with it:
static String readFirstLineFromFile(String path) throws IOException {
try (BufferedReader br =
new BufferedReader(new FileReader(path))) {
return br.readLine();
}
}
In this example, the resource declared in the try-with-resources statement is a BufferedReader. The declaration statement appears within parentheses immediately after the try keyword. The class BufferedReader
, in Java SE 7 and later, implements the interface java.lang.AutoCloseable
. Because the BufferedReader
instance is declared in a try-with-resource statement, it will be closed regardless of whether the try statement completes normally or abruptly (as a result of the method BufferedReader.readLine
throwing an IOException
).
Prior to Java SE 7, you can use a finally
block to ensure that a resource is closed regardless of whether the try statement completes normally or abruptly. The following example uses a finally
block instead of a try-with-resources
statement:
static String readFirstLineFromFileWithFinallyBlock(String path)
throws IOException {
BufferedReader br = new BufferedReader(new FileReader(path));
try {
return br.readLine();
} finally {
if (br != null) br.close();
}
}
Please refer to the docs.
Closeable
extends AutoCloseable
, and is specifically dedicated to IO streams: it throws IOException instead of Exception, and is idempotent, whereas AutoCloseable doesn't provide this guarantee.
This is all explained in the javadoc of both interfaces.
Implementing AutoCloseable (or Closeable) allows a class to be used as a resource of the try-with-resources construct introduced in Java 7, which allows closing such resources automatically at the end of a block, without having to add a finally block which closes the resource explicitely.
Your class doesn't represent a closeable resource, and there's absolutely no point in implementing this interface: an IOTest can't be closed. It shouldn't even be possible to instantiate it, since it doesn't have any instance method. Remember that implementing an interface means that there is a is-a relationship between the class and the interface. You have no such relationship here.