“Sneaky Throw” i Java

1. Oversigt

I Java er sneaky kast koncept giver os mulighed for at kaste enhver afkrydset undtagelse uden at definere det eksplicit i metodesignaturen. Dette tillader udeladelse af kaster erklæring, der effektivt efterligner egenskaberne ved en runtime-undtagelse.

I denne artikel vil vi se, hvordan dette gøres i praksis ved at se på nogle kodeeksempler.

2. Om luskede kaster

Kontrollerede undtagelser er en del af Java, ikke JVM. I bytekoden kan vi kaste enhver undtagelse hvor som helst uden begrænsninger.

Java 8 bragte en ny type slutningsregel, der siger, at en kaster T udledes som RuntimeException når det er tilladt. Dette giver mulighed for at implementere luskede kast uden hjælpemetoden.

Et problem med luskede kast er, at du sandsynligvis vil fange undtagelserne i sidste ende, men Java-kompilatoren tillader dig ikke at fange snigkastede afkrydsede undtagelser ved hjælp af undtagelsesbehandler for deres særlige undtagelsestype.

3. Luskede kaster i aktion

Som vi allerede nævnte, kan compileren og Jave Runtime se forskellige ting:

offentligt statisk tomrum luskedeTrow (Throwable e) kaster E {throw (E) e; } private statiske ugyldige kastSneakyIOException () {sneakyThrow (ny IOException ("luskede")); }

Compileren ser signaturen med kaster T udledt til en RuntimeException type, så det tillader, at den ukontrollerede undtagelse udbredes. Java Runtime ser ikke nogen type i kastene, da alle kast er de samme enkle smide e.

Denne hurtige test demonstrerer scenariet:

@Test offentlig ugyldigt nårCallSneakyMethod_thenThrowSneakyException () {prøv {SneakyThrows.throwsSneakyIOException (); } catch (Exception ex) {assertEquals ("sneaky", ex.getMessage (). toString ()); }}

Det er muligt at kaste en kontrolleret undtagelse ved hjælp af bytecode-manipulation, eller Thread.stop (kan kastes), men det er rodet og anbefales ikke.

4. Brug af Lombok-kommentarer

Det @SneakyThrows kommentar fra Lombok giver dig mulighed for at kaste afkrydsede undtagelser uden at bruge kaster erklæring. Dette er praktisk, når du har brug for at hæve en undtagelse fra en metode inden for meget begrænsende grænseflader som f.eks Kan køres.

Sig, at vi kaster en undtagelse indenfra a Kan køres; det vil kun blive videregivet til Tråd's uhåndteret undtagelsesbehandler.

Denne kode vil kaste Undtagelse eksempel, så det er ikke nødvendigt for dig at pakke det ind i en RuntimeException:

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

En ulempe ved denne kode er, at du ikke kan fange en kontrolleret undtagelse, der ikke er deklareret; så det vil ikke kompilere.

Her er den rigtige form til at smide en luskende undtagelse:

@SneakyThrows offentlig ugyldig kørsel () {prøv {kast ny InterruptedException (); } fange (InterruptedException e) {e.printStackTrace (); }}

Og her er testen for denne opførsel:

@Test offentligt ugyldigt nårCallSneakyRunnableMethod_thenThrowException () {prøv {ny SneakyRunnable (). Run (); } fange (Undtagelse e) {assertEquals (InterruptedException.class, e.getStackTrace ()); }}

5. Konklusion

Som vi har set i denne artikel, kan Java-kompilatoren narre til at behandle afkrydsede undtagelser som ukontrolleret.

Som altid er koden tilgængelig på GitHub.


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