Начиная с седьмой версии Java предлагает улучшенное управление ресурсами, которые должны быть закрыты после окончания работы с ними. К таким ресурсам относятся, например, файлы потоки, соединения с базами данных и сокетами. Этой цели служит специальная языковая конструкция try-with-resources. Для того чтобы это автоматическое закрытие работало создан специальный интерфейс
В Java 7 все классы ресурсов реализуют этот интерфейс. Его сигнатура выглядит следующим образом:
AutoCloseable.
public interface AutoCloseable {
void close() throws Exception;
}
Интерфейс объявляет метод close(), который автоматически вызывается для объектов, обслуживаемых конструкцией try-with-resources.
Несмотря на то, что классы ресурсов в Java 7 реализуют этот интерфейс, множество библиотек, которыми вы пользуетесь этого не делают, поскольку библиотеку еще не обновили для работы с интерфейсом AutoCloseable или же вы просто не имеете возможности обновить библиотеку.
В большинстве случаев это решается просто. Наследуйте класс ресурса, который должен участвовать в конструкции try-with-resources. Возьмем для примера ITextRenderer (из проекта Flying Saucer). После окончания работы с ITextRenderer, должен быть вызван метод finishPDF(). Обычно вы бы делали это в блоке finally. Но создавая новый класс, расширяющий ITextRenderer и реализующий интерфейс AutoCloseable, вы можете включить его в конструкцию try-with-resources. Новый класс AutoCloseableITextRenderer будет при этом выглядеть так:
public class AutoCloseableITextRenderer extends ITextRenderer implements AutoCloseable {
@Override
public void close() {
super.finishPDF();
}
}
Расширение оригинального класса в потомке, является наиболее разумным решением, поскольку новый класс по прежнему будет ITextRenderer. В случае, если исходный класс объявлен как final, необходимо использовать композицию. И вот как при этом будет выглядеть использование:
try (final AutoCloseableITextRenderer iTextRenderer = new AutoCloseableITextRenderer()) {
ByteArrayOutputStream out; // contains the data to be converted to PDF, not shown here.
iTextRenderer.setDocumentFromString(new String(out.toByteArray()));
iTextRenderer.layout();
iTextRenderer.createPDF(pdfOutputStream);
pdfOutputStream.flush();
}
Вот и все.
Пожалуйста, обратите внимание, что я не выбрасывал исключение из метода close() в классе AutoCloseableITextRenderer. В Javadoc интерфейса AutoCloseable по этому поводу сказано следующее:
Хотя в метод интерфейса декларирован выбрасывать исключения Exception, реализующим этот метод настоятельно рекомендуется использовать при реализации метода более специфические классы исключений, или вообще не выбрасывать исключений, если метод close() не может упасть.