Verschil tussen gooien en gooien in Java

1. Inleiding

In deze zelfstudie bekijken we de werpen en gooit in Java. We zullen uitleggen wanneer we ze allemaal moeten gebruiken.

Vervolgens laten we enkele voorbeelden zien van hun basisgebruik.

2. Werpen en Gooit

Laten we beginnen met een korte introductie. Deze trefwoorden hebben betrekking op het afhandelen van uitzonderingen. Er worden uitzonderingen gemaakt wanneer de normale doorstroming van onze applicatie wordt verstoord.

Er kunnen veel redenen zijn. Een gebruiker kan de verkeerde invoergegevens verzenden. We kunnen een verbinding verbreken of er kan zich een andere onverwachte situatie voordoen. Een goede afhandeling van uitzonderingen is een sleutel om onze applicatie te laten werken na een optreden van die onaangename momenten.

We gebruiken werpen trefwoord om expliciet een uitzondering te genereren van de code. Het kan elke methode of statisch blok zijn. Deze uitzondering moet een subklasse zijn van Gooibaar. Het kan ook een Gooibaar zelf. We kunnen niet meerdere uitzonderingen gooien met een enkele werpen.

Gooit trefwoord kan in de methode-declaratie worden geplaatst. Het geeft aan welke uitzonderingen op deze methode kunnen worden geworpen. We moeten deze uitzonderingen aanpakken met try-catch.

Deze twee trefwoorden zijn niet uitwisselbaar!

3. Werpen in Java

Laten we eens kijken naar een eenvoudig voorbeeld met het gooien van een uitzondering op de methode.

Stel je allereerst voor dat we een eenvoudige rekenmachine schrijven. Een van de fundamentele rekenkundige bewerkingen is deling. Daarom werd ons gevraagd om deze functie te implementeren:

openbare dubbele kloof (dubbel a, dubbel b) {retourneer a / b; }

Omdat we niet kunnen delen door nul, moeten we enkele wijzigingen aan onze bestaande code toevoegen. Het lijkt erop dat het een goed moment is om een ​​uitzondering op te werpen.

Laten we dit doen:

openbare dubbele verdeling (dubbele a, dubbele b) {if (b == 0) {throw new ArithmeticException ("Divider kan niet gelijk zijn aan nul!"); } retourneer a / b; }

Zoals u kunt zien, hebben we gebruikt ArithmeticException met perfect past bij onze behoeften. We kunnen een enkele passeren Draad constructor-parameter die een uitzonderingsbericht is.

3.1. Goede oefeningen

We moeten altijd de voorkeur geven aan de meest specifieke uitzondering. We moeten een klas vinden die het beste bij ons uitzonderlijke evenement past. Gooi bijvoorbeeld NumberFormatException in plaats van IllegalArgumentException. We moeten vermijden om een ​​niet-specifiek te gooien Uitzondering.

Er is bijvoorbeeld een Geheel getal les in java.lang pakket. Laten we eens kijken naar de verklaring van de fabrieksmethode:

public static Integer valueOf (String s) genereert NumberFormatException 

Het is een statische fabrieksmethode die creëert Geheel getal instantie van Draad. Bij verkeerde invoer Draad, zal de methode gooien NumberFormatException.

Een goed idee is om onze eigen, meer beschrijvende uitzondering te definiëren. In onze Rekenmachine klasse die bijvoorbeeld zou kunnen zijn DivideByZeroException.

Laten we eens kijken naar de voorbeeldimplementatie:

openbare klasse DivideByZeroException breidt RuntimeException uit {openbare DivideByZeroException (String-bericht) {super (bericht); }}

3.2. Een bestaande uitzondering inpakken

Soms willen we een bestaande uitzondering verpakken in de door ons gedefinieerde uitzondering.

Laten we beginnen met het definiëren van onze eigen uitzondering:

public class DataAcessException breidt RuntimeException uit {public DataAcessException (String bericht, Throwable oorzaak) {super (bericht, oorzaak); }}

De constructor heeft twee parameters: uitzonderingsbericht en een oorzaak, die elke subklasse kan zijn van Gooibaar.

Laten we een nepimplementatie schrijven voor vind alle() functie:

openbare lijst findAll () gooit SQLException {throw nieuwe SQLException (); }

Nu in SimpleService laten we een repository-functie aanroepen, wat kan resulteren in SQLE Uitzondering:

public void wrappingException () {probeer {personRepository.findAll (); } catch (SQLException e) {throw nieuwe DataAccessException ("SQL Exception", e); }}

We gooien opnieuw SQLException verpakt in onze eigen uitzondering genaamd DataAccessException. Alles wordt geverifieerd door de volgende test:

@Test ongeldig whenSQLExceptionIsThrown_thenShouldBeRethrownWithWrappedException () {assertThrows (DataAccessException.class, () -> simpleService.wrappingException ()); }

Hiervoor zijn twee redenen. Allereerst gebruiken we exception wrapping, omdat de rest van de code niet elke mogelijke exception in het systeem hoeft te kennen.

Ook componenten van een hoger niveau hoeven niets te weten over componenten op het onderste niveau, noch de uitzonderingen die ze veroorzaken.

3.3. Multi-Catch met Java

Soms kunnen de methoden die we gebruiken veel verschillende uitzonderingen opleveren.

Laten we eens kijken naar een uitgebreider try-catch-blok:

probeer {tryCatch.execute (); } catch (ConnectionException | SocketException ex) {System.out.println ("IOException"); } catch (uitzondering ex) {System.out.println ("Algemene uitzondering"); }

De uitvoeren methode kan drie uitzonderingen opleveren: SocketException, ConnectionException, uitzondering. Het eerste vangblok zal vangen ConnectionException of SocketException. Het tweede vangblok zou vangen Uitzondering of een andere subklasse van Uitzondering. Onthoud dat we moeten altijd eerst een meer gedetailleerde uitzondering opvangen.

We kunnen de volgorde van onze vangblokken omwisselen. Dan zouden we nooit vangen SocketException en ConnectionException want alles gaat mee naar de vangst Uitzondering.

4. Gooit in Java

We voegen toe gooit naar de methode-declaratie.

Laten we eens kijken naar een van onze eerdere methodeverklaringen:

public static void execute () gooit SocketException, ConnectionException, Exception

De methode kan meerdere uitzonderingen opleveren. Ze worden door komma's gescheiden aan het einde van een methodedeclaratie. We kunnen zowel aangevinkte als niet-aangevinkte uitzonderingen in het gooit. We hebben het verschil tussen beide hieronder beschreven.

4.1. Gecontroleerde en ongecontroleerde uitzonderingen

Een gecontroleerde uitzondering betekent dat deze wordt gecontroleerd tijdens het compileren. Merk op dat we deze uitzondering moeten afhandelen. Anders moet een methode een uitzondering specificeren met behulp van gooit trefwoord.

De meest voorkomende gecontroleerde uitzonderingen zijn IOException, FileNotFoundException, ParseException. FileNotFoundException kan worden gegooid wanneer we creëren FileInputStream van Het dossier.

Er is een kort voorbeeld:

Bestandsbestand = nieuw bestand ("not_existing_file.txt"); probeer {FileInputStream stream = nieuwe FileInputStream (bestand); } catch (FileNotFoundException e) {e.printStackTrace (); }

We kunnen het gebruik van een try-catch-blok vermijden door gooit naar de methodeverklaring:

private static void uncheckedException () gooit FileNotFoundException {File file = new File ("not_existing_file.txt"); FileInputStream-stream = nieuwe FileInputStream (bestand); }

Helaas moet een functie op een hoger niveau deze uitzondering nog verwerken. Anders moeten we deze uitzondering in methode-declaratie zetten met gooit trefwoord.

Als het tegenovergestelde, ongecontroleerde uitzonderingen worden niet gecontroleerd tijdens het compileren.

De meest voorkomende ongecontroleerde uitzonderingen zijn: ArrayIndexOutOfBoundsException, IllegalArgumentException, NullPointerException.

Ongecontroleerde uitzonderingen worden gegenereerd tijdens runtime. De volgende code genereert een NullPointerException. Waarschijnlijk is het een van de meest voorkomende uitzonderingen op Java.

Het aanroepen van een methode op een null-referentie zal resulteren in deze uitzondering:

openbare ongeldige runtimeNullPointerException () {String a = null; a.lengte (); }

Laten we dit gedrag in de test verifiëren:

@Test ongeldig whenCalled_thenNullPointerExceptionIsThrown () {assertThrows (NullPointerException.class, () -> simpleService.runtimeNullPointerException ()); }

Onthoud dat deze code en test niet veel zin heeft. Het is alleen voor leerdoeleinden om uitzonderingen tijdens runtime uit te leggen.

In Java is elke subklasse van Fout en RuntimeException is een ongecontroleerde uitzondering. Een gecontroleerde uitzondering is al het andere onder de Gooibaar klasse.

5. Conclusie

In dit artikel hebben we het verschil tussen twee Java-sleutelwoorden besproken: werpen en gooit. We hebben het basisgebruik doorgenomen en een beetje over goede praktijken gesproken. Vervolgens hebben we het gehad over aangevinkte en niet-aangevinkte uitzonderingen.

Zoals altijd is de broncode te vinden op onze GitHub.

Als je dieper wilt ingaan op het afhandelen van uitzonderingen in Java, lees dan ons artikel over Java-uitzonderingen.