"Podla bacanja" na Javi

1. Pregled

U Javi je sneaky bacanje Koncept nam omogućuje bacanje bilo koje provjerene iznimke bez da je eksplicitno definiramo u potpisu metode. To omogućuje izostavljanje baca deklaracija, efektivno oponašajući obilježja izuzeća tijekom izvođenja.

U ovom ćemo članku vidjeti kako se to radi u praksi, gledajući neke primjere koda.

2. O podlim bacanjima

Označene iznimke dio su Jave, a ne JVM-a. U bytecode-u možemo izbaciti bilo koju iznimku s bilo kojeg mjesta, bez ograničenja.

Java 8 donijela je novo pravilo zaključivanja tipa koje navodi da a baca T se izvodi kao RuntimeException kad god je dopušteno. To daje mogućnost provođenja podlih bacanja bez pomoćne metode.

Problem s podmukla bacanja jest da vjerojatno na kraju želite uhvatiti iznimke, ali Java kompajler ne dopušta hvatanje potajno izbačenih provjerenih iznimki pomoću rukovatelja iznimkama za njihov određeni tip iznimke.

3. Podmukla bacanja u akciji

Kao što smo već spomenuli, kompajler i Jave Runtime mogu vidjeti različite stvari:

javna statička praznina sneakyThrow (Bacljivo e) baca E {bacanje (E) e; } privatna statička praznina throwsSneakyIOException () {sneakyThrow (novi IOException ("sneaky")); }

Prevoditelj vidi potpis s baca T zaključeno na a RuntimeException tip, tako da omogućuje širenje neprovjerene iznimke. Java Runtime ne vidi nijednu vrstu u bacanju jer su sva bacanja ista, jednostavna baciti e.

Ovaj brzi test prikazuje scenarij:

@Test public void whenCallSneakyMethod_thenThrowSneakyException () {try {SneakyThrows.throwsSneakyIOException (); } catch (Iznimka ex) {assertEquals ("sneaky", ex.getMessage (). toString ()); }}

Moguće je baciti provjerenu iznimku pomoću manipulacije bytecode-om ili Thread.stop (može se baciti), ali neuredan je i ne preporučuje se.

4. Korištenje Lombok napomena

The @SneakyThrows napomena iz Lomboka omogućuje vam bacanje provjerenih izuzetaka bez upotrebe baca deklaracija. Ovo dobro dođe kada trebate izuzeti od metode unutar vrlo restriktivnih sučelja poput Izvodljivo.

Recimo da izuzetak izbacimo iznutra Izvodljivo; bit će proslijeđen samo Nit's neobrađeni rukovatelj iznimkama.

Ovaj kod će baciti Iznimka primjerice, tako da nema potrebe da ga umotavate u RuntimeException:

javna klasa SneakyRunnable implementira Runnable {@SneakyThrows (InterruptedException.class) public void run () {throw new InterruptedException (); }}

Nedostatak ovog koda je taj što ne možete uhvatiti provjerenu iznimku koja nije deklarirana; tako da se neće sastaviti.

Evo ispravnog obrasca za bacanje podle iznimke:

@SneakyThrows javna void run () {try {throw new InterruptedException (); } catch (InterruptedException e) {e.printStackTrace (); }}

Evo i testa za ovo ponašanje:

@Test public void whenCallSneakyRunnableMethod_thenThrowException () {try {new SneakyRunnable (). Run (); } catch (Iznimka e) {assertEquals (InterruptedException.class, e.getStackTrace ()); }}

5. Zaključak

Kao što smo vidjeli u ovom članku, Java kompajler može biti prevaren da provjerene iznimke tretira kao neprovjerene.

Kao i uvijek kod je dostupan na GitHub-u.


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