Najlepszy sposób na wyjście z programu, gdy chcę, aby wyjątek został wyrzucony?
Piszę program Java, który czyta w pliku słów. Program zależy przede wszystkim od tego pliku, więc naprawdę chcę, aby program się skończył, jeśli z jakiegoś powodu istnieje IOException podczas czytania pliku.
Jaki jest najlepszy sposób na zakończenie programu? Myślę, że jestem zmuszony otoczyć moje czytanie plików wewnątrz bloku try/catch, więc czy powinienem dodaćSystem.exit(0)
wewnątrz mojego catch? Na przykład, Czy powinienem zrobić coś takiego jak poniżej?
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); // ???
}
4 answers
Jeśli pozwolisz, aby wyjątek rozprzestrzeniał się aż do metody main()
, program się zakończy. Nie ma potrzeby wywoływania System.exit
, po prostu pozwól wyjątkowi, aby w naturalny sposób powiększył stos (dodając throws IOException
) do niezbędnych metod.
Edit: jak zauważył @ Brian, możesz chcieć złapać IOException
w swojej metodzie main
i zamiast tego wywołać System.exit
, dostarczając czytelny dla człowieka komunikat o błędzie (ślady stosu mogą przestraszyć ludzi). Ponadto, jak powiedział @MeBigFatGuy, wywołanie System.exit
z twojego kodu stos jest złą praktyką i ogranicza możliwość ponownego użycia kodu. Jeśli musisz użyć System.exit
, przechowuj go w ciele metody main
.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-05-30 00:06:44
W porządku. Jednakże 0
jako kod zakończenia oznacza zakończenie programu zgodnie z oczekiwaniami. Będziesz chciał użyć innego numeru;)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-05-30 00:07:44
Jeśli naprawdę chcesz natychmiast zakończyć program, zamiast pozwolić, aby wyższe poziomy programu decydowały, co robić (być może rdzeń Twojego programu zostanie kiedyś rozszerzony, aby umożliwić wybór źródła myfile.txt
z różnych stron internetowych, syntezę mowy na tekst lub bezpośredni transfer mózgu), powinieneś zadzwonić: System.exit(1)
(lub inny niezerowy status wyjścia).
Kod zakończenia 0
mówi powłoce (i procesom nadrzędnym), że wykonanie zostało wykonane normalnie. Niezerowe kody wyjścia Zgłoś błąd. Jest to niezbędne do tworzenia doskonałych narzędzi do powiadamiania administratorów o nieprawidłowych błędach wykonania lub do pisania przyjaznych małych programów:]}
./fiddle_with_words myfile.txt || mail -s "program failed" [email protected]
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-05-30 00:10:21
@gratur pyta w komentarzu o odpowiedź @ skaffman.
Myślę, że to zależy. Jeśli wyjątek ma tylko do bańki w górę małej liczby poziomy, i to ma sens dla metod propagacjiWięc jeśli dobrze rozumiem, pozwalam, aby wyjątek się bańka przez usunięcie bloku try/catch i dodanie "throws IOException" do tej metody (i metody, które wywołują tę metodę, i tak dalej)? Czuję się trochę paskudnie robiąc to, bo teraz muszę dodać kilka "rzutów IOException" wszędzie ... czy moja ohydność jest błędna?
IOException
, to jest to, co należy zrobić. Nie ma nic szczególnie "ohydnego" w zezwalaniu na rozprzestrzenianie się WYJĄTKÓW.
Z drugiej strony, jeśli IOException
musi propagować się przez wiele poziomów i nie ma szans , że może być obsługiwany specjalnie poza pewnym punktem, możesz chcieć: {17]}
- zdefiniuj własny
ApplicationErrorException
, który jest podklasąRuntimeException
, - Złap
IOException
blisko źródła i rzucajApplicationErrorException
na swoim miejscu ... zcause
Zestaw oczywiście, i - Złap wyjątek
ApplicationErrorException
w Twojej metodziemain
.
W punkcie main
, w którym wyłapujesz ApplicationErrorException
, możesz wywołać System.exit()
z niezerowym kodem stanu i opcjonalnie wydrukować lub zapisać ślad stosu. (W rzeczywistości, możesz odróżnić przypadki, w których robisz i nie chcesz śledzenia stosu, specjalizując się w wyjątku "błąd aplikacji".)
Zauważ, że nadal zezwalamy na rozprzestrzenianie się wyjątku do main
... z powodów wyjaśnionych w odpowiedzi @skaffman.
Ostatnią rzeczą, która komplikuje to pytanie, są wyjątki rzucane na stos jakiegoś wątku innego niż main
. Prawdopodobnie nie chcesz, aby wyjątek został obsłużony i przekształcony w System.exit()
na stosie drugiego wątku ... bo to nie da innym wątkom szansy na całkowite zamknięcie. Z drugiej strony, jeśli nic nie zrobisz, domyślnym zachowaniem jest to, że drugi wątek po prostu zakończ z niezakłóconym wyjątkiem. Jeśli nic nie jest join()
-w wątku, może to pozostać niezauważone. Niestety, nie ma prostego rozwiązania "Jeden rozmiar dla wszystkich".
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-05-30 00:38:18