Czy istnieje elegancki sposób obsługi wyjątków, które są wrzucane w finally
bloku?
Na przykład:
try {
// Use the resource.
}
catch( Exception ex ) {
// Problem with the resource.
}
finally {
try{
resource.close();
}
catch( Exception ex ) {
// Could not close the resource?
}
}
Jak uniknąć try
/ catch
w finally
bloku?
Resource
=>Closeable
?Zwykle używam jednej z
closeQuietly
metod worg.apache.commons.io.IOUtils
:źródło
Jeśli używasz Java 7 i
resource
implementujeszAutoClosable
, możesz to zrobić (na przykładzie InputStream):źródło
Prawdopodobnie trochę przesadzone, ale może być przydatne, jeśli pozwalasz wyjątkom pojawiać się i nie możesz rejestrować niczego z poziomu swojej metody (np. Ponieważ jest to biblioteka i wolisz, aby kod wywołujący obsługiwał wyjątki i rejestrowanie):
AKTUALIZACJA: przyjrzałem się temu nieco dokładniej i znalazłem świetny post na blogu od kogoś, kto wyraźnie myślał o tym więcej niż ja: http://illegalargumentexception.blogspot.com/2008/10/java-how-not-to-make -mess-of-stream.html Idzie o krok dalej i łączy dwa wyjątki w jeden, co wydaje mi się przydatne w niektórych przypadkach.
źródło
ignore
Jak Java 7 nie ma już potrzeby, aby wyraźnie bliskich zasobów w końcu zablokować można użyć zamiast spróbować składni -z-zasobów. Instrukcja try-with-resources to instrukcja try, która deklaruje jeden lub więcej zasobów. Zasób to obiekt, który musi zostać zamknięty po zakończeniu działania programu. Instrukcja try-with-resources gwarantuje, że każdy zasób zostanie zamknięty na końcu instrukcji. Jako zasób można użyć dowolnego obiektu, który implementuje java.lang.AutoCloseable, który zawiera wszystkie obiekty implementujące java.io.Closeable.
Załóżmy następujący kod:
Jeśli wystąpi jakikolwiek wyjątek, metoda close zostanie wywołana dla każdego z tych trzech zasobów w odwrotnej kolejności, w jakiej zostały utworzone. Oznacza to, że metoda close zostanie wywołana najpierw dla ResultSetm, następnie dla instrukcji i na końcu dla obiektu Connection.
Ważne jest również, aby wiedzieć, że wszelkie wyjątki, które występują, gdy metody close są wywoływane automatycznie, są pomijane. Te wyłączone wyjątki można pobrać za pomocą metody getsuppressed () zdefiniowanej w klasie Throwable .
Źródło: https://docs.oracle.com/javase/tutorial/essential/exceptions/tryResourceClose.html
źródło
Ignorowanie wyjątków, które występują w bloku „ostatecznie”, jest generalnie złym pomysłem, chyba że wiadomo, jakie będą te wyjątki i jakie warunki będą reprezentować. W normalnym
try/finally
wzorcu użyciatry
blok umieszcza rzeczy w stanie, którego zewnętrzny kod nie będzie oczekiwał, afinally
blok przywraca stan tych rzeczy do tego, czego oczekuje kod zewnętrzny. Kod zewnętrzny, który wyłapuje wyjątek, będzie generalnie oczekiwać, że pomimo wyjątku wszystko zostało przywrócone do plikunormal
stan. Na przykład załóżmy, że jakiś kod rozpoczyna transakcję, a następnie próbuje dodać dwa rekordy; blok „na końcu” wykonuje operację „wycofywania zmian, jeśli nie zostały zatwierdzone”. Obiekt wywołujący może być przygotowany na wystąpienie wyjątku podczas wykonywania drugiej operacji „dodawania” i może oczekiwać, że jeśli przechwyci taki wyjątek, baza danych będzie w stanie, w jakim znajdowała się przed próbą wykonania którejkolwiek z operacji. Jeśli jednak podczas wycofywania wystąpi drugi wyjątek, mogą się zdarzyć złe rzeczy, jeśli wywołujący podejmie jakiekolwiek założenia dotyczące stanu bazy danych. Błąd wycofywania zmian stanowi poważny problem kryzys - taki, który nie powinien zostać przechwycony przez kod oczekujący jedynie wyjątku „Nie udało się dodać rekordu”.Osobiście wolałbym mieć ostateczną metodę wychwytującą wyjątki, które występują, i umieszczania ich w „wyjątku CleanupFailedException”, uznając, że taka awaria stanowi poważny problem i takiego wyjątku nie należy lekceważyć.
źródło
Jedno rozwiązanie, jeśli dwa wyjątki to dwie różne klasy
Ale czasami nie da się uniknąć tej drugiej próby. np. do zamykania strumienia
źródło
Dlaczego chcesz uniknąć dodatkowego bloku? Ponieważ ostatni blok zawiera "normalne" operacje, które mogą zgłosić wyjątek ORAZ chcesz, aby ostatni blok działał całkowicie, MUSISZ przechwytywać wyjątki.
Jeśli nie spodziewasz się, że ostatni blok wyrzuci wyjątek, a mimo to nie wiesz, jak obsłużyć wyjątek (po prostu zrzuciłbyś ślad stosu), pozwól wyjątkowi wypłynąć na stos wywołań (usuń try-catch z końcowego blok).
Jeśli chcesz ograniczyć pisanie, możesz zaimplementować „globalny” zewnętrzny blok try-catch, który będzie przechwytywał wszystkie wyjątki wrzucane do bloków final:
źródło
Po wielu przemyśleniach uważam, że następujący kod jest najlepszy:
Ten kod gwarantuje, że:
źródło
Jeśli możesz, najpierw przetestuj, aby uniknąć błędu.
Powinieneś także prawdopodobnie łapać tylko wyjątki, z których możesz odzyskać, jeśli nie możesz odzyskać, pozwól mu rozprzestrzenić się na najwyższy poziom twojego programu. Jeśli nie możesz przetestować stanu błędu, będziesz musiał otoczyć swój kod blokiem try catch, tak jak już to zrobiłeś (chociaż zalecałbym nadal wychwytywanie określonych, oczekiwanych błędów).
źródło
Możesz zmienić to na inną metodę ...
źródło
Zwykle robię to:
Uzasadnienie: Jeśli skończę z zasobem i jedynym problemem, jaki mam, jest jego zamknięcie, niewiele mogę z tym zrobić. Nie ma też sensu zabijanie całego wątku, jeśli i tak skończę z zasobem.
Jest to jeden z przypadków, w których przynajmniej dla mnie można bezpiecznie zignorować ten zaznaczony wyjątek.
Do dziś nie miałem żadnego problemu z używaniem tego idiomu.
źródło
Zadanie wykonane. Brak testów zerowych. Pojedynczy połów obejmuje wyjątki dotyczące pozyskiwania i wypuszczania. Oczywiście możesz użyć idiomu Wykonaj dookoła i musisz napisać go tylko raz dla każdego typu zasobu.
źródło
Zmiana
Resource
z najlepszej odpowiedzi doCloseable
Implementacje strumieniowe
Closeable
W ten sposób możesz ponownie użyć metody dla wszystkich strumieniźródło
Spotkałem się z podobną sytuacją, w której nie mogłem użyć try z zasobami, ale chciałem też obsłużyć wyjątek pochodzący z zamknięcia, a nie tylko zalogować się i zignorować, jak robi to mechanizm closeQuietly. w moim przypadku nie mam do czynienia ze strumieniem wyjściowym, więc awaria przy zamknięciu jest bardziej interesująca niż zwykły strumień.
źródło