Почему я должен использовать, наконец, чтобы закрыть ресурсы? - PullRequest
5 голосов
/ 04 октября 2011

В большинстве случаев единственное, что я вижу, для чего используется блок finally, это что-то вроде

FileInputStream f;
try{
    f= new FileInputStream("sample.txt");
    //something that uses f and sometimes throws an exception
}
catch(IOException ex){
    /* Handle it somehow */
}
finally{
    f.close();
}

Мой вопрос: если область действия f заканчивается областью включения, зачем нам ее закрыватьв конце концов?

Ответы [ 5 ]

19 голосов
/ 04 октября 2011

Поскольку сборка мусора не , то же самое, что очистка ресурса.

Например, если у вас есть объект JDBC Connection, который выходит за пределы области действия, на сервер базы данных не отправляется сигнал, указывающий, что открытые курсоры и соединения больше не нужны. Без этих сообщений вы в конечном итоге исчерпаете количество доступных вам курсоров и соединений.

То же самое с дескрипторами файла и любым другим ресурсом. Приведи себя в порядок.

6 голосов
/ 04 октября 2011

Хорошо, вы привели плохой пример - я подозреваю, что вы имели в виду что-то вроде FileInputStream - но основная причина в том, что Java не имеет детерминированной финализации.

Область действия переменной f заканчивается блоком, в котором она объявлена ​​(не блоком try), но это не означает, что необязательно нет «живых» ссылок на объект больше - и сборщик мусора не будет ни завершать объект, ни собирать мусор каким-либо детерминистическим способом.

Если вы не хотите оставлять ресурсы без присмотра на произвольный промежуток времени (и откладывать сборку мусора, поскольку финализаторам требуется дополнительный раунд сбора перед окончательным освобождением памяти), вам следует явно закрыть ресурсы.

В основном Java не поддерживает RAII так же, как C ++; Вы не должны пытаться использовать его, как если бы это был C ++.

2 голосов
/ 04 октября 2011

потому что, наконец, вызывается каждый раз, даже если вы получили исключение. Блок finally гарантирует, что файл / соединение будут закрыты.

0 голосов
/ 04 октября 2011

Мы обработали исключение с помощью try catch finally, finally блокирует каждый раз, когда выполняется, но нет гарантии на catch, потому что catch блокируется, только если исключение, переданное в параметре, соответствует. Например, если мы открыли какое-либо соединение с базой данных, поэтому мы должны закрыть его перед выходом, это должно быть реализовано в finally.

0 голосов
/ 04 октября 2011

Причина в том, что Java не гарантирует, что объект будет собираться мусором, как только конкретная ссылка на него выпадает из области видимости. Поэтому для объектов, ссылающихся на ограниченные системные ресурсы, таких как файловый дескриптор, недостаточно ждать сбора мусора.

Обратите внимание, что java.io.File на самом деле не такой объект.

...