CodeGym /Java Blog /Willekeurig /Uitzonderingen op Java
John Squirrels
Niveau 41
San Francisco

Uitzonderingen op Java

Gepubliceerd in de groep Willekeurig
Hallo! In de les van vandaag zullen we het hebben over Java-uitzonderingen. Het dagelijks leven zit vol situaties die we niet voorzien. U staat bijvoorbeeld 's ochtends op voor uw werk en zoekt naar uw telefoonoplader, maar u kunt deze nergens vinden. Je gaat naar de badkamer om te douchen en ontdekt dat de leidingen bevroren zijn. Je stapt in je auto, maar hij start niet. Een mens kan vrij gemakkelijk omgaan met dergelijke onvoorziene omstandigheden. In dit artikel proberen we erachter te komen hoe Java-programma's hiermee omgaan.

Wat is een Java-uitzondering?

In de programmeerwereld worden fouten en onvoorziene situaties bij de uitvoering van een programma uitzonderingen genoemd. In een programma kunnen uitzonderingen optreden als gevolg van ongeldige gebruikersacties, onvoldoende schijfruimte of het wegvallen van de netwerkverbinding met de server. Uitzonderingen kunnen ook het gevolg zijn van programmeerfouten of onjuist gebruik van een API. In tegenstelling tot mensen in de echte wereld, moet een programma precies weten hoe met deze situaties om te gaan. Hiervoor heeft Java een mechanisme dat bekend staat als exception handling.

Een paar woorden over zoekwoorden

Exception handling in Java is gebaseerd op het gebruik van de volgende trefwoorden in het programma:
  • try - definieert een codeblok waar een uitzondering kan optreden;
  • catch - definieert een codeblok waarin uitzonderingen worden afgehandeld;
  • tenslotte - definieert een optioneel codeblok dat, indien aanwezig, wordt uitgevoerd ongeacht de resultaten van het try-blok.
Deze sleutelwoorden worden gebruikt om speciale constructies in de code te maken: try{}catch , try{}catch{}finally , try{}finally{} .
  • throw - gebruikt om een ​​exception op te werpen;
  • throws - gebruikt in de handtekening van de methode om te waarschuwen dat de methode een uitzondering kan genereren.
Een voorbeeld van het gebruik van trefwoorden in een Java-programma:

// This method reads a string from the keyboard

public String input() throws MyException { // Use throws to warn 
// that the method may throw a MyException
      BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
    String s = null;
// We use a try block to wrap code that might create an exception. In this case,
// the compiler tells us that the readLine() method in the 
// BufferedReader class might throw an I/O exception
    try {
        s = reader.readLine();
// We use a catch block to wrap the code that handles an IOException  
    } catch (IOException e) {
        System.out.println(e.getMessage());
// We close the read stream in the finally block
    } finally {
// An exception might occur when we close the stream if, for example, the stream was not open, so we wrap the code in a try block
        try {
            reader.close();
// Handle exceptions when closing the read stream
        } catch (IOException e) {
            System.out.println(e.getMessage());
        }
    }

    if (s.equals("")) {
// We've decided that an empty string will prevent our program from working properly. For example, we use the result of this method to call the substring(1, 2) method. Accordingly, we have to interrupt the program by using throw to generate our own MyException exception type.
        throw new MyException("The string cannot be empty!");
    }
    return s;
}

Waarom hebben we uitzonderingen nodig?

Laten we eens kijken naar een voorbeeld uit de echte wereld. Stel je voor dat een deel van een snelweg een kleine brug heeft met een beperkt draagvermogen. Als een auto die zwaarder is dan de limiet van de brug eroverheen rijdt, kan deze instorten. De situatie voor de chauffeur zou op zijn zachtst gezegd uitzonderlijk worden. Om dit te voorkomen, plaatst de transportafdeling waarschuwingsborden op de weg voordat er iets misgaat. Bij het zien van het waarschuwingsbord vergelijkt een chauffeur het gewicht van zijn of haar voertuig met het maximale gewicht van de brug. Als het voertuig te zwaar is, kiest de chauffeur een omleidingsroute. De transportafdeling maakte het enerzijds mogelijk voor vrachtwagenchauffeurs om indien nodig van route te veranderen, anderzijds waarschuwde zij chauffeurs voor de gevaren op de hoofdweg en ten derde waarschuwde zij chauffeurs dat de brug onder bepaalde omstandigheden niet gebruikt mag worden. Uitzonderingen in Java - 2De mogelijkheid om uitzonderlijke situaties in een programma te voorkomen en op te lossen, zodat het programma kan blijven draaien, is een van de redenen om uitzonderingen in Java te gebruiken. Met het uitzonderingsmechanisme kunt u uw code (API) ook beschermen tegen oneigenlijk gebruik door invoer te valideren (controleren). Stel je nu voor dat je even de transportafdeling bent. Eerst moet u de plaatsen kennen waar automobilisten problemen kunnen verwachten. Ten tweede moet u waarschuwingsborden maken en installeren. En tot slot moet je omleidingen voorzien als er zich problemen voordoen op de hoofdroute. In Java werkt het uitzonderingsmechanisme op een vergelijkbare manier. Tijdens de ontwikkeling gebruiken we een try- blok om "uitzonderingsbarrières" op te bouwen rond gevaarlijke delen van de code, we bieden "back-uproutes" met behulp van een catch {}blok, en we schrijven code die hoe dan ook moet worden uitgevoerd in een finaal{} blok. Als we geen "back-uproute" kunnen bieden of we de gebruiker het recht willen geven om te kiezen, moeten we hem of haar op zijn minst waarschuwen voor het gevaar. Waarom? Stelt u zich eens de verontwaardiging voor van een automobilist die, zonder ook maar één waarschuwingsbord te zien, een bruggetje bereikt waar hij niet overheen kan! Bij het programmeren kunnen we bij het schrijven van onze klassen en methoden niet altijd voorzien hoe ze door andere ontwikkelaars kunnen worden gebruikt. Bijgevolg kunnen we niet de 100% correcte manier voorzien om een ​​uitzonderlijke situatie op te lossen. Dat gezegd hebbende, is het een goede vorm om anderen te waarschuwen voor de mogelijkheid van uitzonderlijke situaties. Met het uitzonderingsmechanisme van Java kunnen we dit doen met de worpentrefwoord — in wezen een verklaring dat het algemene gedrag van onze methode het genereren van een uitzondering inhoudt. Dus iedereen die de methode gebruikt, weet dat hij of zij code moet schrijven om uitzonderingen af ​​te handelen.

Anderen waarschuwen voor "problemen"

Als u niet van plan bent uitzonderingen in uw methode af te handelen, maar anderen wilt waarschuwen dat er uitzonderingen kunnen optreden, gebruikt u het sleutelwoord worpen . Dit trefwoord in de handtekening van de methode betekent dat, onder bepaalde omstandigheden, de methode een uitzondering kan genereren. Deze waarschuwing maakt deel uit van de methode-interface en stelt de gebruikers in staat hun eigen logica voor het afhandelen van uitzonderingen te implementeren. Na worpen specificeren we de typen uitzonderingen die worden gegooid. Deze stammen meestal af van de klasse Exception van Java . Aangezien Java een objectgeoriënteerde taal is, zijn alle uitzonderingen objecten in Java. Uitzonderingen in Java - 3

Uitzonderingshiërarchie

Wanneer er een fout optreedt terwijl een programma wordt uitgevoerd, maakt de JVM een object van het juiste type uit de Java-uitzonderingshiërarchie - een reeks mogelijke uitzonderingen die afstammen van een gemeenschappelijke voorouder - de klasse Throwable . We kunnen uitzonderlijke looptijdsituaties in twee groepen verdelen:
  1. Situaties waaruit het programma niet kan herstellen en de normale werking kan voortzetten.
  2. Situaties waarin herstel mogelijk is.
De eerste groep omvat situaties met een uitzondering die afstamt van de klasse Error . Dit zijn fouten die optreden als gevolg van een JVM-storing, geheugenoverloop of systeemfout. Ze duiden meestal op ernstige problemen die niet door software kunnen worden verholpen. In Java wordt de mogelijkheid van dergelijke uitzonderingen niet gecontroleerd door de compiler, dus staan ​​ze bekend als ongecontroleerde uitzonderingen. Deze groep bevat ook RuntimeExceptions, dit zijn uitzonderingen die afstammen van de uitzonderingclass en worden gegenereerd door de JVM tijdens runtime. Ze worden vaak veroorzaakt door programmeerfouten. Deze uitzonderingen worden ook niet aangevinkt (uitgevinkt) tijdens het compileren, dus u hoeft geen code te schrijven om ze af te handelen. De tweede groep bevat uitzonderlijke situaties die kunnen worden voorzien wanneer u het programma aan het schrijven bent (en dus moet u code schrijven om ze te verwerken). Dergelijke uitzonderingen worden gecontroleerde uitzonderingen genoemd. Als het op uitzonderingen aankomt, bestaat het meeste werk van een Java-ontwikkelaar uit het afhandelen van dergelijke situaties.

Een uitzondering maken

Wanneer een programma wordt uitgevoerd, worden uitzonderingen gegenereerd door de JVM of handmatig met behulp van een throw -instructie. Wanneer dit gebeurt, wordt er een uitzonderingsobject in het geheugen gemaakt, wordt de hoofdstroom van het programma onderbroken en probeert de uitzonderingshandler van de JVM de uitzondering af te handelen.

Afhandeling van uitzonderingen

In Java maken we codeblokken waarbij we anticiperen op de behoefte aan exception handling met behulp van de try{}catch , try{}catch{}finally en try{}finally{} constructies. Uitzonderingen in Java - 4Wanneer een exception wordt gegenereerd in een try- blok, zoekt de JVM naar een geschikte exception-handler in het volgende catch- blok. Als een catch- blok de vereiste uitzonderingshandler heeft, gaat de besturing ernaartoe. Zo niet, dan kijkt de JVM verder in de keten van catch- blokken totdat de juiste handler is gevonden. Na het uitvoeren van een catch- blok wordt de besturing overgedragen aan het optionele finaal- blok. Als een geschikte vangstblok niet wordt gevonden, dan stopt JVM het programma en geeft de stacktracering weer (de huidige stapel methodeaanroepen), nadat eerst het blokkeringsblok (indien aanwezig) is uitgevoerd. Voorbeeld van afhandeling van uitzonderingen:

public class Print {

     void print(String s) {
        if (s == null) {
            throw new NullPointerException("Exception: s is null!");
        }
        System.out.println("Inside print method: " + s);
    }

    public static void main(String[] args) {
        Print print = new Print();
        List list= Arrays.asList("first step", null, "second step");

        for (String s : list) {
            try {
                print.print(s);
            }
            catch (NullPointerException e) {
                System.out.println(e.getMessage());
                System.out.println("Exception handled. The program will continue");
            }
            finally {
                System.out.println("Inside finally block");
            }
            System.out.println("The program is running...");
            System.out.println("-----------------");
        }

    }
    }
Hier zijn de resultaten van de hoofdmethode :

Inside print method: first step
Inside finally block
The program is running...
-----------------
Exception: s is null!
Exception handled. The program will continue
Inside finally block
The program is running...
-----------------
Inside print method: second step
Inside finally block
The program is running...
-----------------
De laatste wordt meestal gebruikt om alle streams te sluiten en alle bronnen vrij te maken die zijn geopend/toegewezen in een try- blok. Bij het schrijven van een programma is het echter niet altijd mogelijk om de sluiting van alle bronnen bij te houden. Om ons leven gemakkelijker te maken, bieden de ontwikkelaars van Java de constructie try-with-resources aan, die automatisch alle bronnen sluit die in een try- blok zijn geopend. Ons eerste voorbeeld kan herschreven worden met try-with-resources :

public String input() throws MyException {
    String s = null;
    try (BufferedReader reader = new BufferedReader(new InputStreamReader(System.in))){
        s = reader.readLine();
   } catch (IOException e) {
       System.out.println(e.getMessage());
   }
    if (s.equals("")) {
        throw new MyException ("The string cannot be empty!");
    }
    return s;
}
Dankzij de Java-mogelijkheden die in versie 7 zijn geïntroduceerd, kunnen we ook het opvangen van heterogene uitzonderingen in één blok combineren, waardoor de code compacter en leesbaarder wordt. Voorbeeld:

public String input() {
    String s = null;
    try (BufferedReader reader = new BufferedReader(new InputStreamReader(System.in))) {
        s = reader.readLine();
        if (s.equals("")) {
            throw new MyException("The string cannot be empty!");
        }
    } catch (IOException | MyException e) {
        System.out.println(e.getMessage());
    }
    return s;
}

het komt neer op

Door uitzonderingen in Java te gebruiken, kunt u uw programma's robuuster maken door "back-uproutes" te maken, catch-blokken te gebruiken om de hoofdcode te scheiden van de code voor het afhandelen van uitzonderingen, en worpen te gebruiken om de verantwoordelijkheid voor het afhandelen van uitzonderingen te verschuiven naar degene die uw methode gebruikt .
Opmerkingen
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION