Альтернативы для System.exit(1)
По разным причинам звоню System.exit
не одобряется при написании Java-приложений, так как я могу уведомить вызывающий процесс, что не все идет по плану?
Редактировать: 1 является standin
для любого ненулевого кода выхода.
8 ответов
Использование System.exit
не одобряется, когда "приложение" действительно является субприложением (например, сервлетом, апплетом) более крупного Java-приложения (сервера): в этом случае System.exit
может остановить JVM и, следовательно, также все другие приложения. В этой ситуации наилучшим вариантом является создание соответствующего исключения, которое может быть перехвачено и обработано средой / сервером приложений.
Если Java-приложение действительно предназначено для запуска в качестве отдельного приложения, в использовании нет ничего плохого System.exit
, в этом случае установка значения выхода является, вероятно, самым простым (и также наиболее используемым) способом сообщения о неудаче или успехе родительскому процессу.
Я согласен с толпой "брось исключение". Одна из причин заключается в том, что вызов System.exit затрудняет использование вашего кода, если вы хотите, чтобы другой код мог его использовать. Например, если вы обнаружите, что ваш класс будет полезен из веб-приложения или какого-либо приложения, потребляющего сообщения, было бы неплохо предоставить этим контейнерам возможность как-то справиться с ошибкой. Контейнер может захотеть повторить операцию, принять решение о регистрации и игнорировании проблемы, отправить электронное письмо администратору и т. Д.
Исключением из этого будет ваш main()
Способ; это может заманить в ловушку Исключение и вызвать System.exit()
с некоторым значением, которое может быть распознано вызывающим процессом или сценарием оболочки.
System.exit()
заблокирует и создаст взаимоблокировку, если поток, который его инициировал, используется в ловушке завершения работы.
Политика нашей компании заключается в том, что нормально (даже предпочтительнее) вызывать System.exit(-1), но только в методах init(). Я определенно подумал бы дважды, прежде чем вызывать его во время обычного потока программы.
Я думаю, что исключение - это то, что вы должны делать, когда что-то идет не так. Таким образом, если ваше приложение не работает как отдельное приложение, вызывающая сторона может отреагировать на него и получить некоторую информацию о том, что пошло не так. Это также легче для целей отладки, потому что вы также получите лучшее представление о том, что пошло не так, когда вы увидите трассировку стека.
Важно отметить, что когда исключение достигает верхнего уровня и, следовательно, заставляет виртуальную машину завершить работу, виртуальная машина возвращает код возврата 1, поэтому внешние приложения, использующие этот код возврата, видят, что что-то пошло не так.
Единственный случай, когда я думаю, что System.exit() имеет смысл, это когда ваше приложение предназначено для вызова приложениями, которые не являются Java, и поэтому должны использовать коды возврата, чтобы увидеть, работает ли ваше приложение или нет, и вы хотите, чтобы эти приложения имели возможность по-разному реагировать на разные вещи, например, вам нужны разные коды возврата.
Создание исключений - лучший способ отправить информацию об определенной ошибке из приложения.
Число не говорит вам так много, как:
Exception at thread 'main': FileNotFoundException "The file 'foo' doesn't exist"
(или что-то близкое к этому)
Это может быть опасно / проблематично в среде веб-сервлетов.
Бросок исключения обычно считается другой альтернативой.
Это не одобряется для нормальных выходов. Если "не все идет по плану", то System.exit в порядке.
Обновление: я должен добавить, что я полагаю, что ваше "1" имеет значение, которое где-то задокументировано.
Мне тоже хочется добавить немного своей соли. Это отличный вопрос, который всегда возникает, когда я пишу приложение.
Как все здесь, кажется, согласны, вам следует быть осторожным, используя System.exit()
, и по возможности используйте исключения. Однако,System.exit()
по-прежнему кажется единственным способом вернуть основную информацию в систему и, следовательно, необходим, если вы хотите сделать свое приложение доступным для сценариев. Если вам это не нужно, просто создайте исключение и покончите с этим.
Но если (и только если) ваше приложение является однопоточным, то его можно использовать - это гарантирует, что никакие другие материалы не будут добавлены, и никакие ресурсы не будут открыты (по крайней мере, если вы постоянно используете try-with-resource idiom, который я настоятельно рекомендую, поскольку он также делает код более чистым и компактным).
С другой стороны, как только ваше приложение создает какой-либо поток, который может записывать ресурсы, System.exit() является полным "нет, нет", потому что он может (и со временем повредит) данные.
Чтобы иметь возможность использовать многопоточное приложение со сценариями и при этом гарантировать целостность данных, моим лучшим решением на данный момент является сохранение любого потока, изменяющего ресурсы, который вы создаете (например, путем последовательного использования фабричного метода, который добавляет поток в список.), а также установка обработчика выключения, который аккуратно завершает каждый поток, прерывая его и присоединяя к нему. Поскольку ловушка выключения также вызываетсяSystem.exit()
, это гарантирует (за вычетом ошибок программирования), что ни один поток не будет убит во время записи ресурса.
О да, возможно, мне даже не стоит об этом упоминать, но: НИКОГДА, НИКОГДА не используйте этот ужасный System.halt()
метод. Он просто стреляет виртуальной машине в голову и не вызывает никакого отключения.