Closeable and autocloseable java
На этом шаге мы рассмотрим интерфейсы AutoCloseable, Closeable и Flushable
Данные интерфейсы имеют большое значение для классов потоков ввода-вывода. Два из них, интерфейсы Closeable и Flushable, были определены в пакете java.io и внедрены в версии JDK 5. Третий, интерфейс AutoCloseable, был внедрен в версии JDK 7 и входит в состав пакета java.lang.
В версии JDK 7 интерфейс AutoCloseable обеспечивает поддержку нового оператора try с ресурсами, который автоматизирует процесс закрытия ресурса. Только объекты классов, реализующих интерфейс AutoCloseable, могут управляться оператором try с ресурсами. В интерфейсе AutoCloseable определяется единственный метод close():
void close() throws Exception;
Этот метод закрывает вызывающий объект, высвобождая любые ресурсы, которыми он может пользоваться. Метод close() вызывается автоматически по завершении оператора try с ресурсами, избавляя от необходимости вызывать его явным образом. Автоматическое закрытие потоков ввода-вывода гарантирует правильность их освобождения, когда они больше не нужны, предотвращая тем самым утечку памяти и другие осложнения.
В интерфейсе Closeable также определяется метод close(). Начиная с версии JDK 7 интерфейс Closeable расширяет интерфейс AutoCloseable. Поэтому в версии JDK 7 любой класс, реализующий интерфейс Closeable, реализует также интерфейс AutoCloseable.
Объекты класса, реализующего интерфейс Flushable, могут принудительно направить буферизованные данные в тот поток вывода, к которому присоединен данный объект. В этом интерфейсе определяется единственный метод flush(), как показано ниже:
void flush() throws IOException;
Очистка потока вывода обычно приводит к тому, что буферизованные данные физически выводятся на базовое устройство. Этот интерфейс реализуется всеми классами, способными направлять данные в поток вывода.
На следующем шаге мы начнем знакомиться с потоками ввода-вывода байтов
Чем отличается Closeable от AutoCloseable?
Интерфейс AutoCloseable появился в седьмой версии Java. Он представляет собой объект, предназначенный для хранения какого-либо ресурса до тех пор, пока он открыт. Он имеет только один метод close(), в котором прописаны команды, выполняемые при закрытии ранее задействованного ресурса. Особенностью данного интерфейса является возможность употреблять его в конструкции, состоящей из блоков try – wth – resource.
Closeable считается предшественником AutoCloseable. Для обеспечения совместимости он все ещё присутствует в Java, но лучше применять AutoCloseable. Если требуется употреблять экземпляры, относящиеся к Closeable в блоках try – wth – resource, то AutoCloseable нужно добавить в качестве родителя.
Основной недостаток Closeable – это ограниченный набор исключений. Благодаря наследованию в AutoCloseable расширен тип исключений от IOExcepton до Excepton.
Кроме этого контракт функции close() в Closeable предполагает идемпотентность, то есть чтобы результат выполнения метода при каждом выполнении был тот же, что и при первом запуске функции. В то же время метод close() в AutoCloseable может иметь различные побочные эффекты.
Обучающий бот с бесплатными тестами и практическими заданиями по Kotlin.
Курсовой проект – разработка Телеграм бота на Котлин для изучения иностранных слов. Включает: техническое задание, руководство по поэтапному написанию с код-ревью, работу с сетью и публикацию на сервере. И другие обучающие материалы в закрытом доступе.
Programming for beginners
a. Closeable interface is introduced in Java 1.5, where as AutoCloseable interface is introduced in Java 1.7.
b. Closeable interface extends AutoCloseable interface.
public interface AutoCloseable
void close() throws Exception;
public interface Closeable extends AutoCloseable
public void close() throws IOException;
c. Closeable.close method is restricted to throw IOException, where as AutoCloseable.close method can throw any Exception.
d. calling this AutoCloseable.close method more than once may have some visible side effect, unlike Closeable.close which is required to have no effect if called more than once.
Closeable, AutoCloseable and try-with-resources statement
Any object that implements java.lang.AutoCloseable interface is a Resource.
When you declare the resources using try with resources statement, then the resources will be closed at the end of try-with-resources statement. Following application confirms the same.
package com.sample.app; import java.io.Closeable; import java.io.IOException; public class ResourcesDemo < private static class MyCloseable implements Closeable < @Override public void close() throws IOException < System.out.println("Closing MyCloseable object"); > > private static class MyAutoCloseable implements AutoCloseable < @Override public void close() throws Exception < System.out.println("Closing MyAutoCloseable object"); > > public static void main(String[] args) < System.out.println("Start Execution. "); try (MyCloseable myCloseable = new MyCloseable(); MyAutoCloseable myAutoCloseable = new MyAutoCloseable();) < // Do some work > catch (Exception e) < e.printStackTrace(); >System.out.println("End Execution. "); > >
Start Execution. Closing MyAutoCloseable object Closing MyCloseable object End Execution.
Stanislav Lozenko Java Blog
Мы рассмотрели с вами иерархии InputStream/OutputStream и Reader/Writer. Я бы хотел немного остановиться на интерфейсах обеих этих групп. Как вы видите на картинке внизу всех объединяет эти два интерфейса.
Closeable
До Java 7 заправлял всем интерфейс Closeable. Он нужен для освобождения ресурсов. К примеру мы работает с текстовым файлом и после работы нам он больше не нужен, поэтому нам необходимо освободить все системные ресурсы связанные с ним чтобы дать шанс другим программам при необходимости работать с этим файлом.
Но что конкретно является ресурсом с точки зрения Java? Это могут быть java.io.InputStream, OutputStream, Reader, Writer, Formatter; java.sql.Connection, Statement, ResultSet и так далее.
public interface Closeable extends AutoCloseable
Интерфейс легковесный и кроме обычного close() он ничего не содержит.
Примечательно что метод close() является идемпотентным. Это значит что если стрим закрыт , то никакого эффекта не произойдёт. Удобно!
В свое время с Closeable было много проблем, потому что достаточно легкого и простого механизма как освободить ресурс не было. Эти нюансы очень хорошо описаны в статье на Хабре, но выделим парочку здесь
OutputStream stream = openSomeStream(); // some logic // . stream.close()
Если в методе openSomeStream() происходит ошибка то stream.close() вы не вызовете поэтому ресурс будет занят процессом, он не освободится.
OutputStream stream = openSomeStream(); try < // что-то делаем со stream >finally
Здесь сам close может вызвать исключение, которое может быть не обработано.
Вот для того, чтобы этой метушни не было, в Java 7 разработчики дали вам возможность делигировать закрытие ресурса через AutoCloseable
AutoCloseable
AutoCloseable позволяет вам не беспокоится о закрытии ресурса, JVM сама будет это делать. Взглянем на интерфейс
public interface AutoCloseable
Ничем не отличается. Почему бы тогда просто не заменить им сам Closeable? Ответ прост: из-за обратной совместимости версий, так как у многих в свое время проекты крутились на 5,6 Java, перевод на «такую» JDK мог бы попросту все сломать. Поэтому Closeable наследуется от AutoCloseable.
Прежде чем использовать его по назначению, давайте с вами сами попробуем имплементировать этот метод.
public class RabbitHole implements AutoCloseable < @Override public void close() throws Exception < System.out.println("Close the rabbit hole, please!"); >>
А теперь просто в методе main() вызовем его через форму try-with-resources.
public static void main(String[] args) < try(RabbitHole rabbitHole = new RabbitHole()) < System.out.println("Knock-knock!"); >catch (Exception e) < // some exception handling >>
Knock-knock! Close the rabbit hole, please!
Как вы видите JVM вызывает метод close() который мы с вами реализовали.
Учитывая то что все старые Closeable реализации уже используют AutoCloseable, то все streams, readers и writers могут быть использованы через try-with-resources.
try(InputStream input = new FileInputStream("file.txt")) < // . >
Рекомендую так же почитать манифест от Блоха на эту тему.