Czy te instrukcje kodu są równoważne? Czy jest między nimi jakaś różnica?
private void calculateArea() throws Exception {
....do something
}
private void calculateArea() {
try {
....do something
} catch (Exception e) {
showException(e);
}
}
Odpowiedzi:
Tak, jest ogromna różnica - ta druga połyka wyjątek (co prawda, pokazując), a pierwsza pozwoli mu się rozmnażać. (Zakładam, że
showException
to nie powoduje powtórzenia.)Więc jeśli wywołasz pierwszą metodę i "zrób coś" nie powiedzie się, to wywołujący będzie musiał obsłużyć wyjątek. Jeśli wywołasz drugą metodę i "zrób coś" zawiedzie, wywołujący w ogóle nie zobaczy wyjątku ... co jest ogólnie złą rzeczą, chyba
showException
że naprawdę obsłużył wyjątek, naprawił wszystko, co było nie tak i ogólnie upewnił się którycalculateArea
osiągnął swój cel.Będziesz w stanie powiedzieć to, ponieważ nie można nazwać pierwszą metodę bez albo łapanie
Exception
się lub deklarując, że metoda może go wyrzucić zbyt.źródło
Pierwszy
throws Exception
, więc dzwoniący musi obsłużyćException
. Drugi przechwytuje i obsługujeException
wewnętrznie, więc wywołujący nie musi wykonywać żadnej obsługi wyjątków.źródło
Tak. Wersja, która deklaruje,
throws Exception
będzie wymagała kodu wywołującego do obsługi wyjątku, podczas gdy wersja, która obsługuje go jawnie, nie będzie.czyli po prostu:
vs. przeniesienie ciężaru obsługi wyjątku na dzwoniącego:
źródło
Tak, jest między nimi ogromna różnica. W pierwszym bloku kodu przekazujesz wyjątek do kodu wywołującego. W drugim bloku kodu radzisz sobie sam. To, która metoda jest poprawna, zależy całkowicie od tego, co robisz. W niektórych przypadkach chcesz, aby kod obsługiwał wyjątek (jeśli plik nie został znaleziony i chcesz go utworzyć, na przykład), ale w innych chcesz, aby kod wywołujący obsługiwał wyjątek (plik nie został znaleziony i muszą określić nowy lub go utworzyć).
Ogólnie rzecz biorąc, nie chcesz też łapać ogólnego wyjątku. Zamiast tego będziesz chciał wyłapać tylko konkretne, takie jak
FileNotFoundException
lubIOException
ponieważ mogą oznaczać różne rzeczy.źródło
Jest jeden konkretny scenariusz, w którym nie możemy używać rzutów, musimy użyć try-catch. Istnieje zasada „Przesłonięta metoda nie może zgłosić żadnego dodatkowego wyjątku poza tym, co zgłasza jej klasa nadrzędna”. Jeśli jest jakiś dodatkowy wyjątek, który powinien zostać obsłużony za pomocą try-catch. Rozważ ten fragment kodu. Istnieje prosta klasa bazowa
i jego klasa pochodna:
Kiedy musimy wywołać funkcję thread.sleep () jesteśmy zmuszeni użyć try-catch, tutaj nie możemy użyć:
ponieważ zastąpiona metoda nie może generować dodatkowych wyjątków.
źródło
Zakładam, że przez „identyczne” masz na myśli zachowanie.
Zachowanie funkcji można określić przez:
1) Wartość zwracana
2) Zgłoszone wyjątki
3) Efekty uboczne (tj. Zmiany w stercie, systemie plików itp.)
W tym przypadku pierwsza metoda propaguje każdy wyjątek, podczas gdy druga nie zgłasza żadnego sprawdzonego wyjątku i połyka również większość niezaznaczonych wyjątków, więc zachowanie JEST inne.
Jeśli jednak zagwarantujesz, że „zrób coś” nigdy nie zgłosi wyjątku, wówczas zachowanie będzie identyczne (chociaż kompilator będzie wymagał od obiektu wywołującego obsługi wyjątku w pierwszej wersji)
--edytować--
Z punktu widzenia projektowania API metody są zupełnie inne w ich umowie. Ponadto nie jest zalecane rzucanie wyjątku klasy. Spróbuj wrzucić coś bardziej konkretnego, aby umożliwić wywołującemu lepszą obsługę wyjątku.
źródło
Jeśli wyrzuciłeś wyjątek, metoda potomna (która przesłania to) powinna obsłużyć wyjątek
przykład:
źródło
Wiele razy chcesz, aby wywołujący obsłużył wyjątek. Powiedzmy, że wywołujący wywołuje metodę, która wywołuje inną metodę, która wywołuje inną metodę, zamiast obsługiwać wyjątek przez każdą metodę, możesz po prostu obsłużyć to wywołującemu. Chyba że chcesz coś zrobić w jednej z metod, gdy ta metoda zawodzi.
źródło
Obiekt wywołujący tej metody będzie musiał albo przechwycić ten wyjątek, albo zadeklarować go do ponownego wygenerowania w sygnaturze metody.
W poniższym przykładzie bloku try-catch. Obiekt wywołujący tę metodę nie musi martwić się obsługą wyjątku, ponieważ został on już załatwiony.
źródło
Powoduje to zgłoszenie wyjątku, więc wywołujący jest odpowiedzialny za obsługę tego wyjątku, ale jeśli wywołujący nie obsługuje wyjątku, może to być przekazane do jvm, co może spowodować nieprawidłowe zakończenie programu.
Natomiast w drugim przypadku:
Tutaj wyjątek jest obsługiwany przez wywoływanego, więc nie ma szans na nieprawidłowe zakończenie programu.
Spróbuj złapać to zalecane podejście.
IMO,
Zgłasza słowo kluczowe najczęściej używane z wyjątkami Checked w celu przekonania kompilatora, ale nie gwarantuje normalnego zakończenia programu.
Słowo kluczowe throws deleguje odpowiedzialność za obsługę wyjątków
na obiekt wywołujący (JVM lub inną metodę).
Słowo kluczowe throws jest wymagane tylko w przypadku zaznaczonych wyjątków, w przypadku wyjątków niezaznaczonych nie jest używane słowo kluczowe throws.
źródło