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.