RFE: make AutoCloseable generic in its exception type

Rob Spoor openjdk at icemanx.nl
Tue Oct 7 19:43:20 UTC 2025


Hi all,

AutoCloseable, as added in Java 7 and unchanged ever since, declares to 
throw Exception from its close() method. That means that anytime someone 
needs to have an AutoCloseable that throws a different exception, they 
must create an interface that extends AutoCloseable and override close() 
only to throw a different (or no) exception. That can become quite 
annoying if you have to do it often. But without such interfaces, we 
cannot use lambdas or method references in try-with-resources without 
having to deal with Exception:

     try (AutoCloseable _ = this::cleanup) {
     } // need to catch or re-throw Exception


I think that making AutoCloseable generic in its exception type is a 
change that's quite simple, yet makes life easier for developers. The 
interface would become this:

     public interface AutoCloseable<X extends Exception> {
         /**
          * <existing javadoc minus throws
          *
          * @throws X if this resource cannot be closed
          */
         void close() throws X;
     }

In its raw form, the interface is exactly what we already have: close() 
throws Exception. Therefore, any use of AutoCloseable that doesn't fill 
in the generic type (including extending interfaces) will work as they 
do now. They can still override close() and change the thrown exception 
type. Interfaces that extend AutoCloseable can fill in the generic type, 
and if the close() method doesn't add additional documentation it can be 
removed completely. Interfaces like Closeable will only have to change 
the extends clause:

     public interface Closeable extends AutoCloseable<IOException> {
         // keep close for its documentation
     }

That doesn't add much value yet, but we can now use it in 
try-with-resources without having to deal with Exception:

     try (AutoCloseable<RuntimeException> c = this::cleanup) {
     } // no need to catch or re-throw RuntimeException


There is one other possible change that can make it even easier, and 
that is adding a factory method like Gatherer.Integrator.of:

     public interface AutoCloseable<X extends Exception> {
         // documentation omitted
         void close() throws X;

         // documentation omitted
         static <X extends Exception> AutoCloseable<X> 
of(AutoCloseable<X> closeable) {
             return closeable;
         }
     }

The try-with-resources can now become even simpler:

    try (var _ = AutoCloseable.of(this::cleanup)) {
    }


There is one possible issue with this "of" method, and that is possible 
incompatibilities with existing implementing classes or extending 
interfaces that already have an "of(AutoCloseable)" method with a 
different return type, or that are not static. I think the chances of 
that are not great, but it still is something to consider.


Any thoughts?



More information about the core-libs-dev mailing list