Czy istnieje sposób na zgłoszenie wyjątku bez dodawania deklaracji rzutów?


81

Mam następującą sytuację.

Mam klasę Java, która dziedziczy z innej klasy bazowej i przesłania metodę. Metoda podstawowa nie zgłasza wyjątków i dlatego nie ma throws ...deklaracji.

Teraz moja własna metoda powinna być w stanie zgłosić wyjątek, ale ja albo mam wybór

  • Połknij wyjątek
  • Dodaj deklarację rzutów

Oba nie są satysfakcjonujące, ponieważ pierwsza z nich po cichu zignorowałby wyjątek (ok, mógłbym wykonać trochę logowania), a druga wygenerowałaby błędy kompilatora z powodu różnych nagłówków metod.

public class ChildClass extends BaseClass {

        @Override 
        public void SomeMethod() {
            throw new Exception("Something went wrong");
        }
}

Odpowiedzi:


99

Możesz rzucać niezaznaczone wyjątki bez konieczności ich deklarowania, jeśli naprawdę chcesz. Niezaznaczone wyjątki rozszerzają się RuntimeException. Nie Errorzaznacza się również elementów uruchamiających, które rozszerzają się, ale powinny być używane tylko w przypadku problemów, których nie można obsłużyć (takich jak nieprawidłowy kod bajtowy lub brak pamięci).

W szczególnym przypadku Java 8 została dodana UncheckedIOExceptiondo pakowania i ponownego przesyłania IOException.


1
Działa świetnie, muszę ponownie zgłosić wyjątek RuntimeException, ponieważ wyjątek pochodzi z innej metody, ale działa świetnie, dzięki.
— Jürgen Steinblock

42

Oto sztuczka:

class Utils
{
    @SuppressWarnings("unchecked")
    private static <T extends Throwable> void throwException(Throwable exception, Object dummy) throws T
    {
        throw (T) exception;
    }

    public static void throwException(Throwable exception)
    {
        Utils.<RuntimeException>throwException(exception, null);
    }
}

public class Test
{
    public static void main(String[] args)
    {
        Utils.throwException(new Exception("This is an exception!"));
    }
}

Zastanawiam się, jak to działa? Zrobię trochę badań, ale czy masz jakieś zasoby, które mogą mi pomóc? :-)
— holmicz 22.11.2016

T wywnioskowane jako RuntimeException. Odpowiedział tutaj stackoverflow.com/questions/41380656/ ... a tutaj stackoverflow.com/questions/31316581/…
— seenimurugan Grudnia

1
Niesamowita sztuczka! Ta sztuczka może również dotyczyć wyrażenia / bloku lambda, aby umożliwić przypisanie metody zaznaczonego wyjątku do interfejsu SAM bez żadnych throwsdeklaracji.
— JasonMing

ma dodatkową super premię polegającą na tym, że nie ma do czynienia z niebezpiecznymi.
— lscoughlin

Dlaczego potrzebujesz parametru dummy? Czy to mogłoby działać bez metody ogólnej?
— Kiruahxh

28

Trzecią opcją jest rezygnacja ze sprawdzania wyjątków (tak jak czasami musi to robić samo standardowe API) i zawinięcie zaznaczonego wyjątku w RuntimeException :

throw new RuntimeException(originalException);

Możesz użyć bardziej szczegółowej podklasy RuntimeException.


10

Chcę tylko dodać alternatywną odpowiedź, czysto do Twojej wiadomości :

Tak, istnieje sposób na throwszgłoszenie sprawdzonego wyjątku bez dodawania deklaracji przy użyciu sun.misc.Unsafeklasy. Jest to opisane w następującym wpisie na blogu:

Zgłoś sprawdzony wyjątek z metody bez deklarowania go

Przykładowy kod:

public void someMethod() {
  //throw a checked exception without adding a "throws"
  getUnsafe().throwException(new IOException());
}

private Unsafe getUnsafe() {
  try {
    Field field = Unsafe.class.getDeclaredField("theUnsafe");
    field.setAccessible(true);
    return (Unsafe) field.get(null);
  } catch (Exception e) {
    throw new RuntimeException(e);
  }
}

Jednak nie jest to zalecane. Lepiej jest zawrzeć niezaznaczony wyjątek, jak opisano w niektórych innych odpowiedziach.


3
Jest powód, dla którego nazywają tę klasę Unsafe.
— OrangeDog

4

Dlaczego nie wyrzucisz niezaznaczonego wyjątku? Nie trzeba tego deklarować.

Istnieją dwie możliwości

  • zawijać z zaznaczonym wyjątkiem z niezaznaczonym.
  • nie pozwól kompilatorowi wiedzieć, że rzucasz sprawdzony wyjątek, np. Thread.currentThread (). stop (e);
  • W Javie 6 możesz ponownie zgłosić wyjątek, jeśli tak jest, finala kompilator wie, które sprawdzone wyjątki zostały przechwycone.
  • W Javie 7 możesz ponownie zgłosić wyjątek, jeśli jest faktycznie ostateczny, tj. Nie zmieniasz go w kodzie.

To później jest bardziej przydatne, gdy rzucasz wyjątek check w swoim kodzie i przechwytujesz go w kodzie wywołującym, ale warstwy pomiędzy nimi nie wiedzą nic o wyjątku.


Druga metoda też jest interesująca. Ale w tej chwili zawijanie wyjątku jest dokładnie tym, czego potrzebuję.
— Jürgen Steinblock


@OrangeDog, skoro to przeczytałeś, czy możesz mi powiedzieć, jaka jest różnica między użyciem funkcji stop () w bieżącym wątku a wyrzuceniem opakowanego wyjątku. ;)
— Peter Lawrey

„Następująca metoda jest behawioralnie identyczna z operacją wyrzutu Javy, ale omija próby kompilatora, aby zagwarantować, że metoda wywołująca zadeklarowała wszystkie sprawdzone wyjątki, które może zgłosić”. Jak jest lepsze opakowanie wyjątku?
— Peter Lawrey

„Zatrzymanie wątku powoduje odblokowanie wszystkich monitorów, które zostały zablokowane. Jeśli którykolwiek z obiektów wcześniej chronionych przez te monitory był w niespójnym stanie, inne wątki mogą teraz wyświetlać te obiekty w stanie niespójnym. [...] W przeciwieństwie do inne niezaznaczone wyjątki [...] użytkownik nie ma żadnego ostrzeżenia, że ​​jego program może być uszkodzony. "
— OrangeDog

4

Tak, jest powód, ale w ogóle nie jest to zalecane, możesz użyć:

Niebezpieczny pakiet Java

getUnsafe().throwException(new IOException());

Ta metoda zgłasza sprawdzony wyjątek, ale kod nie jest zmuszony do przechwytywania ani ponownego zgłaszania. Podobnie jak wyjątek czasu wykonywania.


2

Oto przykład przechwytywania zaznaczonych wyjątków i umieszczania ich w niezaznaczonym wyjątku:

public void someMethod() {
   try {
      doEvil();
   }
   catch (IOException e)
   {
       throw new RuntimeException(e);
   }
}

-1

możesz złapać wyjątek za pomocą bloku try-catch w swojej metodzie przesłoniętej. wtedy nie musisz deklarować instrukcji rzucania.


2
jasne, ale wtedy przełknąłbym wyjątek, który jest dokładnie odwrotnością tego, co chcę osiągnąć;)
— Jürgen Steinblock

-1

Możesz użyć dowolnego wyjątku pochodzącego z samego RuntimeException lub RuntimeException

lub

użyj bloku try-block dla kodu wyrzucającego wyjątki i obsłuż go tam

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.