2009-07-08 13 views
12

Czasami po prostu trzeba złapać Throwable, np. podczas pisania kolejki programu wywołującego, która wywołuje ogólne elementy i musi odzyskać od wszelkich błędów (wspomniany dyspozytor rejestruje wszystkie przechwycone wyjątki, ale w trybie cichym, a następnie wykonywanie jest kontynuowane na innych elementach).Najlepsze wskazówki dotyczące łowienia Throwable w Javie

Najlepszą praktyką, jaką mogę wymyślić, jest zawsze ponowne wyrzucenie wyjątku, jeśli jest to wyjątek InterruptedException, ponieważ oznacza to, że ktoś przerwał mi wątek i chce go zabić.

Kolejna propozycja (który pochodził z komentarzem, a nie odpowiedź) jest zawsze rethrow ThreadDeath

Wszelkie inne najlepsze praktyki?

+2

"ThreadDeath" również powinien zostać ponownie zgłoszony, ale nie powinien być wrzucany w pierwszej kolejności. –

+0

Dlaczego komentarz, jest to po prostu rodzaj odpowiedzi, którą chciałem? – ripper234

Odpowiedz

12

Prawdopodobnie najważniejszym jest, nigdy nie połknąć zaznaczonego wyjątku. Rozumiem przez to, nie rób tego:

try { 
    ... 
} catch (IOException e) { 
} 

chyba, że ​​to, co zamierza. Czasami ludzie połknąć sprawdzane wyjątki, ponieważ nie wiedzą, co z nimi zrobić, lub nie chcą (lub nie mogą) zanieczyszczać ich interfejs za pomocą klauzul "throws Exception".

Jeśli nie wiesz co z nim zrobić, to zrobić:

try { 
    ... 
} catch (IOException e) { 
    throw new RuntimeException(e); 
} 

Drugi, że przychodzi na myśl to, aby upewnić się radzić sobie z wyjątkami. Czytanie pliku powinno wyglądać mniej więcej tak:

FileInputStream in = null; 
try { 
    in = new FileInputStream(new File("..."));; 
    // do stuff 
} catch (IOException e) { 
    // deal with it appropriately 
} finally { 
    if (in != null) try { in.close(); } catch (IOException e) { /* swallow this one */ } 
} 
+2

+1 na nie połknąć sprawdzanego wyjątku - nawet w "pierwszym przejściu". zbyt często te rzeczy są pomijane i ostatecznie poddawane kontroli źródła. w razie wątpliwości przynajmniej wydrukuj ślad stosu. – akf

+0

Jeśli nie możesz sobie z tym poradzić i nie możesz go ponownie rzucić, przynajmniej wydrukuj ten ślad stosu! Śledzenie stosu w dzienniku jest bardzo pomocne w diagnozowaniu problemu. – starblue

+1

Horror sprawdzonych Wyjątków ... wychwyć wyjątek IOException tylko po to, aby zawinąć go w niezaszyfrowany wyjątek i NIE robić z nim nic w ogóle? Oczywiście, to jest to, co musisz zrobić w Javie, chyba że faktycznie wiesz, dlaczego otrzymujesz wyjątek. –

2

Zależy od tego, nad czym pracujesz.

Jeśli tworzysz interfejs API, który ma być używany przez kogoś innego, lepiej jest ponownie rzucić wyjątek lub zawinąć go w niestandardowy wyjątek i rzucić.

Podczas opracowywania aplikacji użytkownika końcowego należy zająć się tym wyjątkiem i zrobić to, co konieczne.

1

Jeśli piszesz w kolejce programu wywołującego, do czasu, gdy wyjątek wróci do ciebie, nie ma sensu robić z nim nic poza rejestrowaniem. Kolejka zdarzeń Swing ma zasadniczo ten typ zachowania.

Alternatywnie można podać podpięcie dla "nie przechwyconego modułu obsługi wyjątków", podobnego do ThreadGroup. Należy pamiętać, że program obsługi może zająć dużo czasu i ostatecznie opóźnić dyspozytora.

Jeśli chodzi o wyjątek InterruptedException: jedyną rzeczą, która się tym przejmuje, jest pętla wysyłkowa, która powinna sprawdzić stan zewnętrzny, aby sprawdzić, czy powinien przerwać przetwarzanie.

+0

Dlaczego sprawdzanie stanu zewnętrznego jest lepsze niż użycie wyjątku InterruptedException jako mechanizmu sygnalizacyjnego? – ripper234

+0

Ponieważ InterruptedException po prostu wskazuje, że ktoś wywołał interrupt() w wątku. Może być wiele powodów, aby to zrobić, a nie tylko zakończyć bieżącą akcję. A jeśli chcesz użyć metody interrupt() w celu zakończenia działania dispatchera, z pewnością nie chcesz go wyrzucać; po prostu wróć z run() - chyba, że ​​twój dyspozytor nie jest jedyną rzeczą, którą robi wątek, ale nawet tam, prawie na pewno nie chcesz ślepo rzucać. – kdgregory

2

Co z OutOfMemoryError (a może jego superklasą VirtualMachineError)? Nie mogę sobie wyobrazić, że jest coś, co możesz zrobić po poważnie.

+1

Jeśli wątek, który przydzielił dużo obiektów, przechwytuje błąd OutOfMemoryError w punkcie, w którym przydzielony obiekt staje się zbiorem nieczytelnym, maszyna wirtualna może odzyskać. Jeśli obiekty nadal są przywoływane, to tak, niewiele można zrobić, oprócz rzucenia lub zwolnienia niektórych obiektów. –

+0

Złap 'VirtualMachineError' jest trudny, ponieważ twój program znajduje się w niezdefiniowanym stanie: http://stackoverflow.com/questions/8728866/no-throw-virtualmachineerror-guarantees – Raedwald