В Java существуют средства автоматического управления памятью. Поиском и освобождением ненужных участков в памяти в JVM занимается специальный процесс, который называется garbage collector (GC). Он работает в фоновом режиме. Программисту на Java, не нужно беспокоиться о таких проблемах, как уничтожение объектов, если они больше не используются. Однако несмотря на то, что в Java этот процесс выполняется автоматически, он не дает 100% гарантии. Не зная, как устроен сборщик мусора и память Java, программист может создать объекты, которые не будут удаляться GC, даже если они больше не используются.
В частности при работе с файловыми потоками может произойти так называемая «утечка ресурса». Если программа использует файл, то по окончании работы с ним, поток должен быть закрыт с помощью метода close() при этом файл автоматически помечается в операционной системе как свободный, чтобы другие программы могли обращаться к этому ресурсу. Если не сделать этого, то ресурс так и останется помеченный как занятый и операционная система будет считать его используемым и никто другой не сможет во время работы программы обратиться к этому ресурсу.
Таким образом при завершении работы с потоком его надо закрыть с помощью метода close(), который определен в интерфейсе Closeable. Метод close() имеет следующей контракт:
void close() throws IOException
Интерфейс Closeable реализуется в классах InputStream и OutputStream, а через них и во всех классах потоков. При закрытии потока освобождаются все выделенные для него ресурсы, например, файл.
Существует два способа закрытия файла. Первый традиционный заключается в использовании блока try…catch…finally.
Пример.
Результат работы программы:
Поскольку при открытии или считывании файла может произойти ошибка ввода-вывода, то код считывания помещается в блок try. И чтобы быть уверенным, что поток в любом случае закроется, даже если при работе с ним возникнет ошибка, вызов метода close() помещается в блок finally. Так как метод close() также в случае ошибки может генерировать исключение IOException, то его вызов также помещается во вложенный блок try…catch.
Замечание.
В примере выше метод close() (строка 18) может сгенерировать исключение. Если же при этом ранее в основном коде работы с ресурсом тоже возникнет исключение, то последнее перезатрется исключением из close(). Информация об исходной ошибке пропадет и уже будет невозможно узнать, что было причиной исходного исключения.
В настоящее время можно использовать еще один способ закрытия файла, который автоматически вызывает метод close(). Этот способ заключается в использовании конструкции try-with-resources (try- с-ресурсами). Данная конструкция работает с объектами, которые реализуют интерфейс AutoCloseable. Так как все классы потоков реализуют интерфейс Closeable, который в свою очередь наследуется от AutoCloseable, то их также можно использовать в данной конструкции Перепишем предыдущий пример с использованием конструкции
try-with-resources.
Пример.
Результат работы программы совпадает с предыдущим. Формат конструкции try-with-resources, следующий:
try(ИмяКласса имяОбъекта = КонструкторКласса(парам)).
Отличительной особенностью является использование круглых скобок у ключевого слова try. В круглых скобках может быть перечислено через точку с запятой несколько операторов, открывающих разные потоки.
Подобная конструкция использовалась, в одном из примеров ранее.
Пример.
try(FileInputStream fin =
new FileInputStream("notes.txt"); FileOutputStream fos =
new FileOutputStream("notes_new.txt"))
{
//блок try
}
Данная конструкция также не исключает использования блоков catch. После окончания работы в блоке try у указанного в круглых скобках ресурса или перечисленных ресурсов (в данном случае у объекта FileInputStream) автоматически вызывается метод close().
Замечание.
Если исключение будет выброшено в основном коде и в методе close(), то приоритетнее будет первое исключение, а второе исключение будет подавлено, но информация о нем сохранится.
Оператор try-с-ресурсами упрощает процесс освобождения ресурсов, исключая даже возможность забыть освободить используемый ресурс по небрежности. Поэтому такой способ освобождения ресурсов рекомендуется применять при всякой возможности в процессе разработки нового кода.
Достарыңызбен бөлісу: |