Question 12 · Section 7

What is the difference between AutoCloseable and Closeable?

Closeable is a special case of AutoCloseable only for I/O operations.

Language versions: English Russian Ukrainian

Junior Level

Short answer

Closeable is a special case of AutoCloseable only for I/O operations.

AutoCloseable (java.lang)
  └── Closeable (java.io)
        └── FileInputStream, BufferedReader, etc.

Key differences

Characteristic Closeable AutoCloseable
Package java.io java.lang
Exception throws IOException throws Exception
Purpose I/O only Any resources

Examples

// Closeable - only I/O
try (FileInputStream fis = new FileInputStream("file.txt")) {
    fis.read();
} // close() throws IOException

// AutoCloseable - any resource
try (Connection conn = dataSource.getConnection()) {
    conn.createStatement().executeQuery("SELECT 1");
} // close() throws SQLException

Which to use

  • For files, streams - Closeable (already implemented in JDK)
  • For custom resources (DB, transactions) - AutoCloseable

Middle Level

Hierarchy (since Java 7)

Closeable inherits AutoCloseable. This was done for backward compatibility - all old I/O classes work in try-with-resources.

Contract differences

Idempotency:

  • Closeable - Javadoc requires idempotency: “if already closed, call has no effect”
  • AutoCloseable - Javadoc recommends: “strongly recommended…”
  • In practice, both should be idempotent.

Reason: some resources (transactions) may throw an exception when trying to close an already closed transaction.

Flushable & Closeable

Many Closeable classes also implement Flushable:

Flushable - interface with flush() method. Flush = flush buffered data. BufferedOutputStream.close() first calls flush() to write buffered data to disk.

public class BufferedOutputStream extends FilterOutputStream
    implements Flushable, Closeable {

    public void close() throws IOException {
        flush(); // Flushes buffer before closing
        out.close();
    }
}

On close, close() typically calls flush(). But this depends on implementation.

Exception Narrowing

When implementing AutoCloseable for your services, remove throws Exception:

// Bad
public class MyService implements AutoCloseable {
    public void close() throws Exception { }
}

// Good
public class MyService implements AutoCloseable {
    public void close() { } // No throws - clean and safe
}

What to implement in your class

  • Closeable - if your class is an I/O stream (works with bytes/characters)
  • AutoCloseable - if your class is any other resource (DB connection, transaction, lock)

Senior Level

Suppressed Exceptions Priority

When closing several resources in TWR, order - LIFO (Last In, First Out). Exception from the most inner resource is added last to the suppressed list.

// When closing A, B, C (in this order), if all three fail: // A - main exception // B and C - suppressed (order: B then C, LIFO)

Interrupted Close

If close() is blocking (closing network pool) and thread is interrupted - InterruptedException. TWR doesn’t magically handle interrupts - you still need catch.

Static Analysis

instanceof Closeable also means instanceof AutoCloseable. But not vice versa!

Edge Cases

  • Transactional resources - close() may mean “commit”. Repeated call must be safe
  • Shared resources - if resource is used by multiple components, closing one must not break others

Diagnostics

In Highload systems, file descriptor leak due to wrong choice between these interfaces in custom wrappers - one of the most common causes of JVM crash after several days of operation.

  • lsof -p <pid> - shows open file descriptors
  • jstack - shows blocked threads in close()
  • Metrics - track number of open connections via Micrometer

Interview Cheat Sheet

Must know:

  • Closeable inherits from AutoCloseable (hierarchy: AutoCloseable <- Closeable)
  • Closeable in java.io, throws IOException; AutoCloseable in java.lang, throws Exception
  • Closeable - only for I/O streams; AutoCloseable - for any resources (DB, transactions, locks)
  • Both should be idempotent, but for Closeable it’s a strict Javadoc requirement
  • When implementing, narrow exception type or remove throws completely
  • Close order in TWR - LIFO (last opened closed first)

Frequent follow-up questions:

  • Which interface to implement in your class? - Closeable if it’s an I/O stream, AutoCloseable for everything else
  • What is Exception Narrowing? - When implementing AutoCloseable, replace throws Exception with specific type or remove
  • Why does Closeable throw IOException? - Historically: created for I/O operations, where IOException is the only expected error
  • What happens if you close a shared resource from two components? - Second call must be safe (idempotency); otherwise - architecture bug

Red flags (NOT to say):

  • “They are the same” - Different packages, contracts, and purposes
  • “AutoCloseable throws only RuntimeException” - Throws Exception (checked), but you can narrow
  • “Close order doesn’t matter” - LIFO is critical: outermost resource closes last

Related topics:

  • [[11. What is the AutoCloseable interface]]
  • [[9. What is try-with-resources]]
  • [[10. What are the requirements for resources in try-with-resources]]
  • [[23. What are suppressed exceptions]]
  • [[18. What is exception wrapping (wrapping)]]