Byłem ostatnio zaskoczony, gdy odkryłem, że możliwe jest posiadanie instrukcji return w końcowym bloku w Javie.
Wygląda na to, że wiele osób uważa, że zrobienie czegoś złego, jak opisano w sekcji „ Nie wracaj w klauzuli na końcu ”. Zagłębiając się nieco głębiej, znalazłem również „ zwrot Javy nie zawsze ”, który pokazuje całkiem okropne przykłady innych typów kontroli przepływu w ostatecznie blokach.
Tak więc moje pytanie brzmi: czy ktoś może mi podać przykład, w którym instrukcja return (lub inna kontrola przepływu) w bloku Final tworzy lepszy / bardziej czytelny kod?
źródło
Miałem NAPRAWDĘ trudny czas, aby wyśledzić błąd lata temu, który był przez to spowodowany. Kod wyglądał mniej więcej tak:
Zdarzyło się, że wyjątek został odrzucony w innym kodzie. Został złapany, zarejestrowany i ponownie wyrzucony w ramach
somethingThatThrewAnException()
metody. Ale wyjątek nie był propagowany w przeszłościproblemMethod()
. Po długim czasie przyglądania się temu w końcu wyśledziliśmy to do metody zwrotu. Metoda powrotu w bloku final w zasadzie zatrzymywała propagację wyjątku, który wystąpił w bloku try, mimo że nie został przechwycony.Jak powiedzieli inni, chociaż powrót z końcowego bloku jest legalny zgodnie ze specyfikacją Java, jest to ZŁA rzecz i nie należy tego robić.
źródło
javac ostrzeże o powrocie w końcu, jeśli użyjesz -Xlint: w końcu. Pierwotnie javac nie emitował żadnych ostrzeżeń - jeśli coś jest nie tak z kodem, kompilacja powinna się nie powieść. Niestety kompatybilność wsteczna oznacza, że nie można zabronić nieoczekiwanej genialnej głupoty.
Wyjątki mogą być wyrzucane z ostatecznych bloków, ale w tym przypadku wykazywane zachowanie jest prawie na pewno tym, czego chcesz.
źródło
Dodawanie struktur kontrolnych i powrót do bloków w końcu {} to kolejny przykład nadużyć typu „tylko dlatego, że można”, które są rozproszone po praktycznie wszystkich językach programowania. Jason miał rację, sugerując, że może to łatwo stać się koszmarem związanym z konserwacją - argumenty przeciwko wczesnym zwrotom z funkcji odnoszą się bardziej do tego przypadku „późnych zwrotów”.
W końcu bloki istnieją w jednym celu, abyś mógł całkowicie uporządkować siebie, bez względu na to, co wydarzyło się w całym poprzednim kodzie. Zasadniczo jest to zamykanie / zwalnianie wskaźników do plików, połączeń z bazą danych itp., Chociaż widziałem, że jest to rozciągane, aby powiedzieć, że dodaje się audyt na zamówienie.
Wszystko, co wpływa na powrót funkcji, powinno znajdować się w bloku try {}. Nawet gdybyś miał metodę, za pomocą której sprawdziłeś stan zewnętrzny, wykonałeś czasochłonną operację, a następnie sprawdziłeś ten stan ponownie na wypadek, gdyby stał się nieważny, nadal chciałbyś, aby drugie sprawdzenie w try {} - jeśli w końcu siedział w środku {} a długa operacja nie powiodła się, wtedy sprawdzałbyś ten stan po raz drugi niepotrzebnie.
źródło
Prosty test Groovy:
Wynik:
Pytanie:
Ciekawym punktem dla mnie było zobaczenie, jak Groovy radzi sobie z niejawnymi zwrotami. W Groovy możliwe jest „zwrócenie” metody po prostu pozostawienie wartości na końcu (bez powrotu). Jak myślisz, co się stanie, jeśli odkomentujesz linię runningThreads.remove (..) w instrukcji last - czy spowoduje to nadpisanie zwykłej zwracanej wartości („OK”) i zakrycie wyjątku ?!
źródło
Powrót z wnętrza
finally
bloku spowodujeexceptions
zagubienie.Instrukcja return wewnątrz bloku finala spowoduje odrzucenie każdego wyjątku, który może zostać zgłoszony w bloku try lub catch.
Zgodnie ze specyfikacją języka Java:
Uwaga: zgodnie z JLS 14.17 - instrukcja zwrotu zawsze kończy się nagle.
źródło