AutoCloseable vs Closeable

Naveen AnamaneniUpdated · 4 min read

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

TwoInterfaces.java▶ Try it
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()));
    }
}
Output
Closeable extends AutoCloseable
AutoCloseable.close() throws [class java.lang.Exception]
Closeable.close() throws [class java.io.IOException]

How it works

  1. Closeable extends AutoCloseable, so every Closeable can be used in try-with-resources too.
  2. AutoCloseable.close() is declared to throw any Exception; Closeable.close() narrows that to IOException.

The Differences

AutoCloseableCloseable
Packagejava.langjava.io
SinceJava 7Java 5
close() may throwExceptionIOException
Calling close() twiceNot required to be safe (but should be)Must have no effect the second time (idempotent)
Used byJDBC Connection, ExecutorService, Scanner's parent types, your own resourcesStreams, readers, writers, channels

Which Should Your Class Implement?

Your resourceImplement
Wraps a file, stream or socket, and closing can fail with an I/O errorCloseable
Anything else that must be released: a lock, a timer, a connection to a serviceAutoCloseable

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:

NoThrows.java▶ Try it
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");
        }
    }
}
Output
locked by Srihitha
updating the shared file
unlocked

Because 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

  1. Easy: Change Lock to implement Closeable instead. Does main still compile? Why?
  2. Harder: Add a closed flag to Lock so a second close() prints nothing, and test it by calling close() manually inside the try block.

Quick check: AutoCloseable vs Closeable

4 questions
1Which interface does Closeable extend?
2What may AutoCloseable.close() throw?
3Which must be safe to close twice?
4Your Timer class can't fail when closing. What should close() declare?

Key Takeaways

Was this tutorial helpful?

Lesson 224 of 482