Mikor dobja a Java a nem bejelentett, dobható kivételt?

Java Top

Most jelentettem be az újat Tanulj tavaszt tanfolyam, amelynek középpontjában az 5. tavasz és a tavaszi bakancs 2 alapjai állnak:

>> ELLENŐRIZZE A FOLYAMATOT

1. Áttekintés

Ebben az oktatóanyagban meg fogjuk nézni, hogy mi okozza a Java-t a UndeclaredThrowableException kivétel.

Először egy kis elmélettel kezdünk. Ezután két valós példával megpróbáljuk jobban megérteni ennek a kivételnek a természetét.

2. A UndeclaredThrowableException

Elméletileg a Java dobni fog példányt UndeclaredThrowableException amikor megpróbálunk be nem jelentett bejelölt kivételt dobni. Vagyis nem deklaráltuk a bejelölt kivételt a dob záradékot, de ezt a kivételt a módszer törzsébe dobjuk.

Azt állíthatjuk, hogy ez lehetetlen, mivel a Java fordító fordítási hibával megakadályozza ezt. Például, ha megpróbálunk fordítani:

public void be nem jelentett () {dobja új IOException (); }

A Java fordító nem sikerül a következő üzenettel:

java: be nem jelentett kivétel java.io.IOException; el kell fogni vagy el kell dobni

Annak ellenére, hogy a be nem jelentett, bejelölt kivételek dobása nem fordulhat elő fordítási időben, mégis futási időben lehetséges. Vegyük például egy futásidejű proxy elfogását egy olyan módszerrel, amely nem vet ki kivételeket:

public void save (Object data) {// kihagyva}

Ha maga a proxy ellenőrzött kivételt dob, a hívó szemszögéből a mentés metódus dobja az ellenőrzött kivételt. A hívó valószínűleg nem tud semmit erről a proxyról, és hibáztatja a mentés erre a kivételre.

Ilyen körülmények között a Java beilleszti a tényleges ellenőrzött kivételt egy UndeclaredThrowableException és dobja a UndeclaredThrowableException helyette. Érdemes megemlíteni, hogy a UndeclaredThrowableException maga ellenőrizetlen kivétel.

Most, hogy eleget tudunk az elméletről, nézzünk meg néhány valós példát.

3. Java dinamikus proxy

Első példaként hozzunk létre egy futásidejű proxyt a java.util.List interfészt és lehallgatják a módszerhívásait. Először is meg kell valósítanunk a InvocationHandler felületet, és tegye oda az extra logikát:

public class ExceptionalInvocationHandler implementálja az InvocationHandler {@Orride public Object invoke (Object proxy, Method method, Object [] args) Throwable {if ("size" .equals (method.getName ())) {dob új SomeCheckedException ("Mindig sikertelen" dobást) ); } dob új RuntimeException (); }} public class SomeCheckedException kiterjeszti a Exception {public SomeCheckedException (String üzenet) {super (message); }}

Ez a proxy ellenőrzött kivételt dob, ha a proxy módszer az méret. Ellenkező esetben ellenőrizetlen kivételt dob.

Lássuk, hogyan kezeli a Java mindkét helyzetet. Először felhívjuk a List.size () módszer:

ClassLoader classLoader = getClass (). GetClassLoader (); InvocationHandler invocationHandler = new ExceptionalInvocationHandler (); Lista proxy = (Lista) Proxy.newProxyInstance (classLoader, új Class [] {List.class}, invocationHandler); assertThatThrownBy (proxy :: size) .isInstanceOf (UndeclaredThrowableException.class) .hasCauseInstanceOf (SomeCheckedException.class);

Amint a fentiekből látható, létrehozunk egy proxyt a Lista felületet, és hívja a méret módszer rajta. A proxy viszont elfogja a hívást, és dob egy ellenőrzött kivételt. Ezután a Java beburkolja ezt az ellenőrzött kivételt a UndeclaredThrowableException.Ez azért történik, mert valahogy bedobunk egy bejelölt kivételt anélkül, hogy deklarálnánk a metódus deklarációban.

Ha más módszert hívunk a Lista felület:

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

Mivel a proxy ellenőrizetlen kivételt dob, a Java hagyja, hogy a kivétel a jelenlegi állapotban terjedjen.

4. Tavaszi szempont

Ugyanez történik, amikor egy ellenőrzött kivételt dobunk a Tavaszi aspektusba, miközben a javasolt módszerek nem nyilatkoztak róluk. Kezdjük egy kommentárral:

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

Most tanácsot adunk az ezzel a feljegyzéssel ellátott összes módszerre:

@Aspect @Component public class UndeclaredAspect {@Around ("@ annotation (undeclared)") public Object advisise (ProceedingJoinPoint pjp, ThrowUndeclared undeclared) dob Throwable {dob új SomeCheckedException ("AOP ellenőrzött kivétel"); }}

Alapvetően ez a tanács minden megjegyzéssel ellátott metódust megtesz az ellenőrzött kivétel eldöntésére, még akkor is, ha nem nyilvánítottak ilyen kivételt. Most hozzunk létre egy szolgáltatást:

@Service public class UndeclaredService {@ThrowUndeclared public void doSomething () {}}

Ha meghívjuk az annotált metódust, a Java dob egy példányt UndeclaredThrowableException kivétel:

@RunWith (SpringRunner.class) @SpringBootTest (class = UndeclaredApplication.class) public class UndeclaredThrowableExceptionIntegrationTest {@Autowired private UndeclaredService service; @Test public void givenAnAspect_whenCallingAdvisedMethod_thenShouldWrapTheException () {assertThatThrownBy (service :: doSomething) .isInstanceOf (UndeclaredThrowableException.class) .hasCauseInstanceOf (SomeChack) }}

Amint fentebb látható, a Java okként összefoglalja a tényleges kivételt, és a UndeclaredThrowableException kivétel helyett.

5. Következtetés

Ebben az oktatóanyagban azt láttuk, hogy mi okozza a Java-t a UndeclaredThrowableException kivétel.

Szokás szerint az összes példa elérhető a GitHubon.

Java alsó

Most jelentettem be az újat Tanulj tavaszt tanfolyam, amelynek középpontjában az 5. tavasz és a tavaszi bakancs 2 alapjai állnak:

>> ELLENŐRIZZE A FOLYAMATOT

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