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); // ???
}
Author: grautur, 2011-05-30

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.

 33
Author: skaffman,
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;)

 8
Author: Brian Roach,
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]
 8
Author: sarnold,
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.

Wię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?

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 propagacji 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 rzucaj ApplicationErrorException na swoim miejscu ... z cause Zestaw oczywiście, i
  • Złap wyjątek ApplicationErrorException w Twojej metodzie main.

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".

 4
Author: Stephen C,
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