В чем разница между интерфейсами AutoCloseable и Closeable в Java
Что проверяют
Знаете ли вы, как эти интерфейсы связаны и почему в JDK их два. Следом почти всегда просят объяснить, что происходит с исключением из close() в try-with-resources и в каком порядке закрываются ресурсы.
Как отвечать
Closeable: появился в Java 5 в пакетеjava.io, методclose()бросаетIOException. Контракт требует идемпотентности: повторный вызовclose()на закрытом ресурсе ничего не делает;AutoCloseable: добавлен в Java 7 вjava.langвместе сtry-with-resources. Егоclose()объявлен сthrows Exception, идемпотентность только настойчиво рекомендуется;- иерархия:
CloseableрасширяетAutoCloseable, а не наоборот. В Java 7 его встроили в новую иерархию, чтобы все потоки ввода-вывода сразу заработали вtry-with-resources.
Отсюда практическое правило. Для ресурса ввода-вывода реализуйте Closeable. Для всего остального, например обёртки над блокировкой, соединением или пулом, берите AutoCloseable, но сужайте сигнатуру: переопределённый close() может объявить конкретное исключение или вообще никакого. Тогда вызывающему коду не придётся ловить голый Exception.
Про try-with-resources стоит сказать три вещи. Ресурсы закрываются в обратном порядке объявления. Если упал и основной блок, и close(), наружу летит исключение из блока, а исключение закрытия прикрепляется к нему и доступно через getSuppressed(). С Java 9 в заголовок можно передать уже объявленную effectively final переменную: try (reader) { ... }.
Примеры из JDK: InputStream и Reader реализуют Closeable, а JDBC-интерфейсы Connection, Statement, ResultSet, стримы Stream и, начиная с Java 19, ExecutorService реализуют AutoCloseable.
Где спотыкаются
Путают направление наследования и говорят, что AutoCloseable расширяет Closeable.
Считают throws Exception преимуществом. Это скорее неудобство: широкое исключение заставляет вызывающий код ловить всё подряд, поэтому сигнатуру в реализации сужают.
Закрывают ресурс вручную в finally и теряют причину сбоя: исключение из close() перекрывает основное, тогда как try-with-resources сохранил бы его как подавленное.