Функция может через FileNotFoundException, но я чувствую, называя это, а затем сделать что-то на основе попытке поймать это плохая практика.
Я не согласен. IMO, он проверяет, существует ли файл перед открытием, что является плохой практикой. Сравните эти два варианта кода:
File f = new File("someFile");
InputStream is;
Версия # 1
if (f.exists()) {
is = new FileInputStream(f);
...
} else {
System.err.println("Doesn't exist");
}
Версия # 2
try {
is = new FileInputStream(f);
...
} catch (FileNotFoundException ex) {
System.err.println("Doesn't exist");
}
Там целый ряд проблем, с первой версией:
Версия №1 делает дополнительную сист вызов em, когда вы звоните f.exists()
. Это делает первую версию более медленной в среднем, если не существует высокой вероятности того, что файл не будет.
Версия №1 имеет состояние гонки. Если какой-то внешний процесс удаляет файл примерно в одно и то же время, вы можете получить file.exists()
, возвращающий true, а затем создатель FileInputStream
, бросающий FileNotFoundException
. Это состояние гонки, которое может быть использовано для взлома защиты, если этот файл является критическим для безопасности. (На самом деле, есть второе условие гонки тоже, где файл создается и file.exists()
возвращает ложь, когда последующая попытка открыть удастся. Но это состояние гонки, вероятно, безвредны.)
Другая проблема состоит в что FileInputStream
объявлен как метать IOException
. Тестирование, чтобы увидеть, существует ли файл, касается только одного из возможных режимов отказа. В любом случае ваш код придется ловить и иметь дело с другими IOException
.
@Pieces прокомментировал:
Исключения должны быть, когда что-то идет не так, что вы не имеете никакого контроля над. В этом случае я полностью контролирую его.
На самом деле, у вас нет полного контроля над ним. Конечно, не в общем случае. Даже в вашем конкретном случае использования, состояние гонки все еще возможно в теории.
Но настоящая проблема с этим мышлением заключается в том, что вы в конечном итоге прыгаете через обручи, чтобы избежать исключений в ситуациях, когда исключения/обработка исключений - это решение best. Это делает код более сложным, менее читаемым и потенциально медленным и/или более хрупким.
Нормальная догма выглядит следующим образом:
«Исключения должны использоваться только в исключительных ситуациях».
Это не то же самое, что сказать то, что вы сказали. Слово «исключительный» на самом деле просто означает «не нормально». Это имеет гораздо более широкий смысл, чем «что-то пошло не так, что вы не контролируете».
Я склонен расширить догмат следующим образом:
Исключение не должны быть использован для нормального управления потоком.
Исключения не должны быть использованы, если они собираются оказаться слишком дорогим в среднем.
Исключения Следует использовать, если тесты, которые вы использовали бы, чтобы избежать их, ненадежны.
Исключения должны быть использованы, если тесты вы будете использовать, чтобы избежать их слишком дорого в среднем.
Исключения Следует использовать, если они значительно упрощают ваш код (по модулю выше). И критерием простоты является то, читается ли код средним программистом Java.
(Примечание - «в среднем» и «слишком дорого» ...)
Теперь можно утверждать, пока коровы не пришли домой о как исключительная событие должно быть, но я считаю, что на самом деле это вопрос балансировки относительной простоты подходов (в контексте) по сравнению со средними затратами на производительность (в контексте). Любое догматическое правило, которое не учитывает компромиссы и контекст, в некоторых случаях наносит вам вред.
Примечание: использование File.exists() таким образом 1) не защищает от всех исключений, 2) оставляет вас открытыми для условий гонки, а 3) делает вас медленнее в программе ... если несуществующие файлы сценарий * вероятно *. –
Я предпочитаю первый метод, так как он сохраняет непрозрачность относительно того, где файл на самом деле – njzk2