Kedy hodí Java UndeclaredThrowableException?

Java Top

Práve som oznámil nové Naučte sa jar kurz zameraný na základy jari 5 a Spring Boot 2:

>> SKONTROLUJTE KURZ

1. Prehľad

V tomto výučbe sa pozrieme na to, čo spôsobí, že Java hodí inštanciu súboru UndeclaredThrowableException výnimkou.

Najprv začneme trochou teórie. Potom sa pokúsime lepšie pochopiť podstatu tejto výnimky pomocou dvoch príkladov zo skutočného sveta.

2. The UndeclaredThrowableException

Teoreticky vzaté, Java vloží inštanciu UndeclaredThrowableException keď sa pokúsime vyhodiť nedeklarovanú zaškrtnutú výnimku. To znamená, že sme nedeklarovali kontrolovanú výnimku v hodí klauzula, ale túto výnimku hodíme do tela metódy.

Niekto by mohol namietať, že je to nemožné, pretože kompilátor Java tomu zabráni chybou kompilácie. Napríklad, ak sa pokúsime zostaviť:

public void undeclared () {throw new IOException (); }

Kompilátor Java zlyhá so správou:

java: nenahlásená výnimka java.io.IOException; musia byť chytení alebo vyhlásení za hodení

Aj keď sa prihodenie nevyhlásených kontrolovaných výnimiek nemusí stať počas kompilácie, za behu je to stále možnosť. Uvažujme napríklad, že runtime proxy zachytáva metódu, ktorá nevyvoláva žiadne výnimky:

public void save (údaje objektu) {// vynechané}

Pokiaľ proxy sám vyhodí kontrolovanú výnimku, z pohľadu volajúceho, uložiť metóda vyvolá túto kontrolovanú výnimku. Volajúci pravdepodobne o tomto zástupcovi nič nevie a bude to obviňovať uložiť pre túto výnimku.

Za takýchto okolností Java zabalí skutočne skontrolovanú výnimku do UndeclaredThrowableException a hodiť UndeclaredThrowableException namiesto toho. Za zmienku stojí, že UndeclaredThrowableException sama o sebe je nekontrolovaná výnimka.

Teraz, keď vieme dosť o teórii, pozrime sa na niekoľko príkladov z reálneho sveta.

3. Java Dynamic Proxy

Ako náš prvý príklad vytvorme runtime proxy pre java.util.List rozhranie a zachytávať jeho volania metód. Najprv by sme mali implementovať InvocationHandler rozhranie a vložte tam ďalšiu logiku:

verejná trieda ExceptionalInvocationHandler implementuje InvocationHandler {@Override verejné vyvolanie objektu (Object proxy, metóda metódy, Object [] args) hodí Throwable {if ("size" .equals (method.getName ())) {throw new SomeCheckedException ("Always failed" ); } hodiť nový RuntimeException (); }} verejná trieda SomeCheckedException rozširuje výnimku {public SomeCheckedException (reťazcová správa) {super (správa); }}

Tento proxy server vyvolá kontrolovanú výnimku, ak je použitá proxy metóda veľkosť. V opačnom prípade vyvolá nekontrolovanú výnimku.

Pozrime sa, ako Java zvláda obe situácie. Najprv zavoláme List.size () metóda:

ClassLoader classLoader = getClass (). GetClassLoader (); InvocationHandler invocationHandler = nový ExceptionalInvocationHandler (); Zoznam proxy = (Zoznam) Proxy.newProxyInstance (classLoader, nová trieda [] {List.class}, invocationHandler); assertThatThrownBy (proxy :: size) .isInstanceOf (UndeclaredThrowableException.class) .hasCauseInstanceOf (SomeCheckedException.class);

Ako je uvedené vyššie, vytvárame proxy pre server Zoznam rozhranie a zavolajte veľkosť metóda na to. Proxy server zase zachytí hovor a vyhodí zaškrtnutú výnimku. Potom Java zabalí túto kontrolovanú výnimku do inštancie UndeclaredThrowableException.Toto sa deje, pretože nejako hodíme kontrolovanú výnimku bez toho, aby sme ju deklarovali v deklarácii metódy.

Ak zavoláme inú metódu na Zoznam rozhranie:

assertThatThrownBy (proxy :: isEmpty) .isInstanceOf (RuntimeException.class);

Pretože proxy server vrhá nekontrolovanú výnimku, Java nechá túto výnimku šíriť sa tak, ako je.

4. Jarný aspekt

To isté sa stane, keď hodíme kontrolovanú výnimku do jarného aspektu, zatiaľ čo odporúčané metódy ich nedeklarujú. Začnime anotáciou:

@Target (ElementType.METHOD) @Retention (RetentionPolicy.RUNTIME) public @interface ThrowUndeclared {}

Teraz poradíme všetky metódy anotované touto anotáciou:

@Aspect @Component verejná trieda UndeclaredAspect {@Around ("@ annotation (undeclared)") public Object Consult (ProceedingJoinPoint pjp, ThrowUndeclared undeclared) hodí Throwable {throw new SomeCheckedException ("AOP Checked Exception"); }}

V zásade táto rada urobí všetky anotované metódy na vyhodenie kontrolovanej výnimky, aj keď takúto výnimku nedeklarujú. Teraz vytvorme službu:

@Service verejná trieda UndeclaredService {@ThrowUndeclared public void doSomething () {}}

Ak zavoláme anotovanú metódu, Java hodí inštanciu UndeclaredThrowableException výnimka:

@RunWith (SpringRunner.class) @SpringBootTest (classes = UndeclaredApplication.class) verejná trieda UndeclaredThrowableExceptionIntegrationTest {@Autowired súkromná služba UndeclaredService; @Test public void givenAnAspect_whenCallingAdvisedMethod_thenShouldWrapTheException () {assertThatThrownBy (service :: doSomething) .isInstanceOf (UndeclaredThrowableException.class) .hasCauseInstanceOf (SomeCheckedException.class); }}

Ako je uvedené vyššie, Java zapuzdruje skutočnú výnimku ako príčinu a hodí znak UndeclaredThrowableException namiesto toho výnimka.

5. Záver

V tomto návode sme videli, čo spôsobuje, že Java hodí inštanciu súboru UndeclaredThrowableException výnimkou.

Ako obvykle sú všetky príklady dostupné na GitHub.

Java dole

Práve som oznámil nové Naučte sa jar kurz zameraný na základy jari 5 a Spring Boot 2:

>> SKONTROLUJTE KURZ

$config[zx-auto] not found$config[zx-overlay] not found