AutoCloseable vs Closeable
To work with try-with-resources, a class implements an interface with a single close() method. There are two such interfaces: java.io.Closeable, the original from Java 5 for I/O streams, and java.lang.AutoCloseable, added in Java 7 as the more general parent. They look almost identical, but they differ in which exceptions close() may throw and in a promise about calling close() twice.
Asking Java
import java.io.Closeable;
import java.util.Arrays;
public class TwoInterfaces {
public static void main(String[] args) throws Exception {
System.out.println("Closeable extends "
+ Closeable.class.getInterfaces()[0].getSimpleName());
System.out.println("AutoCloseable.close() throws "
+ Arrays.toString(AutoCloseable.class.getMethod("close")
.getExceptionTypes()));
System.out.println("Closeable.close() throws "
+ Arrays.toString(Closeable.class.getMethod("close")
.getExceptionTypes()));
}
}Closeable extends AutoCloseable
AutoCloseable.close() throws [class java.lang.Exception]
Closeable.close() throws [class java.io.IOException]How it works
CloseableextendsAutoCloseable, so everyCloseablecan be used in try-with-resources too.AutoCloseable.close()is declared to throw anyException;Closeable.close()narrows that toIOException.
The Differences
AutoCloseable | Closeable | |
|---|---|---|
| Package | java.lang | java.io |
| Since | Java 7 | Java 5 |
close() may throw | Exception | IOException |
Calling close() twice | Not required to be safe (but should be) | Must have no effect the second time (idempotent) |
| Used by | JDBC Connection, ExecutorService, Scanner's parent types, your own resources | Streams, readers, writers, channels |
Which Should Your Class Implement?
| Your resource | Implement |
|---|---|
| Wraps a file, stream or socket, and closing can fail with an I/O error | Closeable |
| Anything else that must be released: a lock, a timer, a connection to a service | AutoCloseable |
Either way, narrow the exception in your own close(). If it can't fail, declare no exception at all, so callers don't need a catch just for closing:
public class NoThrows {
static class Lock implements AutoCloseable {
Lock() { System.out.println("locked by Srihitha"); }
@Override
public void close() {
System.out.println("unlocked");
}
}
public static void main(String[] args) {
try (Lock lock = new Lock()) {
System.out.println("updating the shared file");
}
}
}locked by Srihitha
updating the shared file
unlockedBecause close() declares no checked exception, main needs no catch at all.
Common Mistakes
Declaring close() throws Exception when nothing can fail. It forces every user to catch Exception.
Implementing Closeable for something that isn't I/O. AutoCloseable is the right, more general choice.
A close() that fails the second time. For Closeable it breaks the contract.
Interview Corner
What is the difference between AutoCloseable and Closeable?
AutoCloseable (java.lang, Java 7) is the general interface required by try-with-resources; its close() may throw Exception. Closeable (java.io, Java 5) extends it for I/O resources; its close() throws only IOException and must be idempotent, so calling it more than once has no further effect. Any Closeable can be used in try-with-resources.
Practice
- Easy: Change
Lockto implementCloseableinstead. Doesmainstill compile? Why? - Harder: Add a
closedflag toLockso a secondclose()prints nothing, and test it by callingclose()manually inside the try block.
Key Takeaways
Was this tutorial helpful?