"Sneaky Throws" in Java

1. Overzicht

In Java is de sneaky worp concept stelt ons in staat om elke aangevinkte uitzondering te genereren zonder deze expliciet in de methodehandtekening te definiëren. Hierdoor kan de gooit declaratie, waarmee de kenmerken van een runtime-uitzondering effectief worden nagebootst.

In dit artikel zullen we zien hoe dit in de praktijk gebeurt, aan de hand van enkele codevoorbeelden.

2. Over stiekeme worpen

Gecontroleerde uitzonderingen maken deel uit van Java, niet de JVM. In de bytecode kunnen we elke uitzondering overal vandaan gooien, zonder beperkingen.

Java 8 heeft een nieuwe inferentieregel voor het type geïntroduceerd die stelt dat a gooit T wordt afgeleid als RuntimeException wanneer toegestaan. Dit geeft de mogelijkheid om stiekeme worpen te implementeren zonder de helper-methode.

Een probleem met stiekeme worpen is dat je waarschijnlijk de uitzonderingen uiteindelijk wilt opvangen, maar de Java-compiler staat je niet toe om stiekem gegooide gecontroleerde uitzonderingen op te vangen met behulp van een exception handler voor hun specifieke exception-type.

3. Sneaky Throws in actie

Zoals we al zeiden, kunnen de compiler en de Jave Runtime verschillende dingen zien:

openbare statische leegte sneakyThrow (Throwable e) gooit E {worp (E) e; } privé statische leegte throwsSneakyIOException () {sneakyThrow (nieuwe IOException ("sneaky")); }

De compiler ziet de handtekening met de gooit T afgeleid naar een RuntimeException type, dus het staat de ongecontroleerde uitzondering toe om door te geven. De Java Runtime ziet geen enkel type in de worpen, omdat alle worpen hetzelfde zijn gooi e.

Deze snelle test demonstreert het scenario:

@Test openbare leegte whenCallSneakyMethod_thenThrowSneakyException () {probeer {SneakyThrows.throwsSneakyIOException (); } catch (uitzondering ex) {assertEquals ("sneaky", ex.getMessage (). toString ()); }}

Het is mogelijk om een ‚Äč‚Äčaangevinkte uitzondering te genereren met behulp van bytecode-manipulatie, of Thread.stop (werpbaar), maar het is rommelig en niet aan te raden.

4. Lombok-annotaties gebruiken

De @BuienRadarNL annotatie van Lombok stelt je in staat om aangevinkte uitzonderingen te gooien zonder de gooit verklaring. Dit is handig wanneer u een uitzondering moet maken van een methode binnen zeer beperkende interfaces zoals Loopbaar.

Stel dat we een uitzondering maken vanuit een Runnable; het wordt alleen doorgegeven aan de Draad's onverwerkte uitzonderingshandler.

Deze code gooit de Uitzondering U hoeft het dus niet in een RuntimeException:

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

Een nadeel van deze code is dat je een aangevinkte uitzondering die niet gedeclareerd is, niet kunt afvangen; dus het zal niet compileren.

Hier is het juiste formulier voor het gooien van een stiekeme uitzondering:

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

En hier is de test voor dit gedrag:

@Test openbare leegte whenCallSneakyRunnableMethod_thenThrowException () {probeer {nieuwe SneakyRunnable (). Run (); } catch (uitzondering e) {assertEquals (InterruptedException.class, e.getStackTrace ()); }}

5. Conclusie

Zoals we in dit artikel hebben gezien, kan de Java-compiler worden misleid om aangevinkte uitzonderingen als niet aangevinkt te behandelen.

Zoals altijd is de code beschikbaar op GitHub.