Подтвердить что ты не робот

Лучший способ выйти из программы, когда я хочу, чтобы исключение было выбрано?

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

Какой лучший способ закончить программу? Я думаю, что я вынужден окружать чтение файла внутри блока try/catch, поэтому я должен добавить System.exit(0) внутри моего catch? Например, должен ли я сделать что-то вроде следующего?

try {
  BufferedReader br = new BufferedReader(new FileReader("myfile.txt"));
  String line;
  while ((line = br.readLine()) != null) {
    // process...
  }
} catch(IOException e) {
  System.out.println("Error: " + e);
  System.exit(0); // ???
}
4b9b3361

Ответ 1

Если вы разрешаете исключение распространяться вплоть до метода main(), программа завершится. Нет необходимости вызывать System.exit, просто разрешить исключение для естественного размытия стека (путем добавления throws IOException) к необходимым методам.

Изменить: Как отметил @Brian, вы можете захотеть поймать IOException в своем методе main и вместо этого вызвать System.exit вместо этого, предоставляя сообщение с возможностью чтения человеком (трассировки стека могут напугать людей). Кроме того, как сказал @MeBigFatGuy, вызов System.exit изнутри вашего стека кода является плохой практикой и ограничивает возможность повторного использования кода. Если вы должны использовать System.exit, то сохраните его внутри тела метода main.

Ответ 2

Это хорошо. Однако 0 как код выхода означает, что программа закончилась, как ожидалось. Вы захотите использовать другое число;)

Ответ 3

Если вы действительно хотите немедленно прекратить работу программы, а не позволить верхним уровням программы решить, что делать (возможно, ядро ​​вашей программы будет расширено, чтобы позволить выбрать источник для myfile.txt с разных сайтов, синтез речи или текста или прямой перенос мозга), вы должны вызвать: System.exit(1) (или какой-либо другой ненулевой статус выхода).

Код завершения 0 указывает оболочке (и родительским процессам), что выполнение выполнено нормально. Не нулевые коды выхода сообщают, что произошла ошибка. Это важно для создания отличных инструментов для уведомления администраторов о ненормальных ошибках выполнения или для написания дружественных небольших программ:

./fiddle_with_words myfile.txt || mail -s "program failed" [email protected]

Ответ 4

@gratur спрашивает в ответ на ответ @skaffman.

Итак, если я правильно понимаю, я разрешаю исключению пузыря, удалив блок try/catch и добавляя к этому методу "throws IOException" (и методы, вызывающие этот метод, и т.д.)? Я чувствую себя от этого нехорошим, потому что теперь мне нужно добавить кучу "исключений IOException" повсюду - моя ложь ошибочна?

Я думаю, это зависит. Если исключение только должно пузырить небольшое количество уровней, и имеет смысл для методов распространять IOException, то это то, что вы должны делать. Нет ничего особенно "нехорошего" в том, чтобы разрешить распространение исключения.

С другой стороны, если IOException должен распространяться через многие уровни, и нет никаких шансов, что он может быть обработан специально за пределами определенной точки, вы можете:

  • определить пользовательский ApplicationErrorException, который является подклассом RuntimeException,
  • поймайте IOException рядом с его источником и выбросьте ApplicationErrorException на свое место... с помощью cause, конечно, и
  • поймать исключение ApplicationErrorException в вашем методе main.

В точке main, где вы ловите ApplicationErrorException, вы можете вызвать System.exit() с ненулевым кодом состояния и, при необходимости, распечатать или записать трассировку стека. (Фактически, вы можете различать случаи, когда вы делаете, и не хотите трассировки стека, специализируясь на исключении "ошибка приложения".)

Обратите внимание, что мы по-прежнему разрешаем исключение распространяться на main... по причинам, объясняемым в ответе @skaffman.


Последнее, что усложняет этот вопрос, - это исключения, которые бросаются в стек какого-либо потока, отличного от потока main. Вероятно, вы не хотите, чтобы исключение обрабатывалось и превращалось в System.exit() в другой поток стека... потому что это не даст другим потокам возможность отключиться. С другой стороны, если вы ничего не делаете, поведение по умолчанию заключается в том, что другой поток просто заканчивается с неперехваченным исключением. Если ничто не соответствует join(), то это может остаться незамеченным. К сожалению, нет простого решения "одного размера подходит всем".