CodeGym /Java blogg /Slumpmässig /Undantag i Java
John Squirrels
Nivå
San Francisco

Undantag i Java

Publicerad i gruppen
Hallå! I dagens lektion kommer vi att prata om Java-undantag. Vardagen är full av situationer som vi inte förutser. Du går till exempel upp till jobbet på morgonen och letar efter din telefonladdare, men du hittar den inte någonstans. Du går till badrummet för att duscha bara för att upptäcka att rören är frusna. Du sätter dig i din bil, men den startar inte. En människa klarar ganska lätt av sådana oförutsedda omständigheter. I den här artikeln ska vi försöka ta reda på hur Java-program hanterar dem.

Vad är ett Java-undantag?

I programmeringsvärlden kallas fel och oförutsedda situationer i exekveringen av ett program för undantag. I ett program kan undantag uppstå på grund av ogiltiga användaråtgärder, otillräckligt diskutrymme eller förlust av nätverksanslutningen till servern. Undantag kan också bero på programmeringsfel eller felaktig användning av ett API. Till skillnad från människor i den verkliga världen måste ett program veta exakt hur man hanterar dessa situationer. För detta har Java en mekanism som kallas undantagshantering.

Några ord om nyckelord

Undantagshantering i Java baseras på användningen av följande nyckelord i programmet:
  • try - definierar ett kodblock där ett undantag kan inträffa;
  • catch - definierar ett kodblock där undantag hanteras;
  • slutligen - definierar ett valfritt kodblock som, om det finns, exekveras oavsett resultaten av försöksblocket.
Dessa nyckelord används för att skapa speciella konstruktioner i koden: try{}catch , try{}catch{}finally , try {}finally{} .
  • kasta - används för att höja ett undantag;
  • throws - används i metodsignaturen för att varna för att metoden kan ge ett undantag.
Ett exempel på hur du använder nyckelord i ett Java-program:

// 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;
}

Varför behöver vi undantag?

Låt oss titta på ett exempel från den verkliga världen. Föreställ dig att en del av en motorväg har en liten bro med begränsad viktkapacitet. Om en bil som är tyngre än brons gräns kör över den kan den kollapsa. Situationen för föraren skulle bli milt uttryckt exceptionell. För att undvika detta sätter transportavdelningen upp varningsskyltar på vägen innan något går fel. När en förare ser varningsskylten jämför han sitt fordons vikt med maxvikten för bron. Om fordonet är för tungt tar föraren en förbifartsväg. Transportavdelningen gjorde det för det första möjligt för lastbilschaufförer att ändra sin rutt vid behov, för det andra varnade förarna för farorna på huvudvägen och för det tredje varnade förarna att bron inte får användas under vissa förhållanden. Undantag i Java - 2Möjligheten att förhindra och lösa exceptionella situationer i ett program, så att det kan fortsätta att köras, är en anledning till att använda undantag i Java. Undantagsmekanismen låter dig också skydda din kod (API) från felaktig användning genom att validera (kontrollera) eventuella indata. Föreställ dig nu att du är transportavdelningen för en sekund. Först måste du känna till de platser där bilister kan förvänta sig problem. För det andra måste du skapa och installera varningsskyltar. Och slutligen måste du tillhandahålla omvägar om problem uppstår på huvudvägen. I Java fungerar undantagsmekanismen på liknande sätt. Under utvecklingen använder vi ett försöksblock för att bygga en "undantagsbarriär" runt farliga kodavsnitt, vi tillhandahåller "backuprutter" med en fångst {}block, och vi skriver kod som ska köras oavsett vad i ett finally{}- block. Om vi ​​inte kan tillhandahålla en "backup-rutt" eller vi vill ge användaren rätt att välja, måste vi åtminstone varna honom eller henne för faran. Varför? Föreställ dig bara indignationen hos en förare som utan att se en enda varningsskylt når en liten bro som han inte kan ta sig över! I programmering, när vi skriver våra klasser och metoder, kan vi inte alltid förutse hur de kan användas av andra utvecklare. Som ett resultat kan vi inte förutse det 100 % korrekta sättet att lösa en exceptionell situation. Som sagt, det är bra att varna andra om möjligheten till exceptionella situationer. Javas undantagsmekanism låter oss göra detta med kastennyckelord — i huvudsak en förklaring om att vår metods allmänna beteende inkluderar att göra ett undantag. Därför vet alla som använder metoden att han eller hon bör skriva kod för att hantera undantag.

Varnar andra för "problem"

Om du inte planerar att hantera undantag i din metod, men vill varna andra för att undantag kan förekomma, använd nyckelordet throws . Detta nyckelord i metodsignaturen innebär att metoden under vissa förutsättningar kan ge ett undantag. Denna varning är en del av metodgränssnittet och låter dess användare implementera sin egen logik för undantagshantering. Efter kast anger vi vilka typer av undantag som kastas. Dessa härstammar vanligtvis från Javas Exception -klass. Eftersom Java är ett objektorienterat språk är alla undantag objekt i Java. Undantag i Java - 3

Undantagshierarki

När ett fel uppstår medan ett program körs, skapar JVM ett objekt av lämplig typ från Java-undantagshierarkin - en uppsättning möjliga undantag som härstammar från en gemensam förfader - Throwable- klassen . Vi kan dela upp exceptionella körtidssituationer i två grupper:
  1. Situationer från vilka programmet inte kan återhämta sig och fortsätta normal drift.
  2. Situationer där återhämtning är möjlig.
Den första gruppen inkluderar situationer som involverar ett undantag som härstammar från klassen Error . Dessa är fel som uppstår på grund av ett JVM-fel, minnesspill eller systemfel. De indikerar vanligtvis allvarliga problem som inte kan fixas med programvara. I Java kontrolleras inte möjligheten för sådana undantag av kompilatorn, så de är kända som okontrollerade undantag. Denna grupp inkluderar även RuntimeExceptions, som är undantag som härstammar från undantagetklass och genereras av JVM vid körning. De orsakas ofta av programmeringsfel. Dessa undantag är inte heller kontrollerade (avmarkerade) vid kompilering, så du behöver inte skriva kod för att hantera dem. Den andra gruppen inkluderar exceptionella situationer som kan förutses när du skriver programmet (och därför bör du skriva kod för att hantera dem). Sådana undantag kallas kontrollerade undantag. När det kommer till undantag är det mesta av en Java-utvecklares arbete att hantera sådana situationer.

Skapar ett undantag

När ett program körs genereras undantag antingen av JVM eller manuellt med en throw -sats. När detta händer skapas ett undantagsobjekt i minnet, programmets huvudflöde avbryts och JVM:s undantagshanterare försöker hantera undantaget.

Undantagshantering

I Java skapar vi kodblock där vi förutser behovet av undantagshantering med konstruktionerna try{}catch , try{}catch{}finally och try{}finally{} . Undantag i Java - 4När ett undantag kastas i ett försöksblock , letar JVM efter en lämplig undantagshanterare i nästa fångstblock . Om ett fångstblock har den nödvändiga undantagshanteraren, överförs kontrollen till det. Om inte, så tittar JVM längre ner i kedjan av fångstblock tills rätt hanterare hittas. Efter exekvering av ett fångstblock överförs kontrollen till det valfria finalblocket . Om en lämplig fångstblocket inte hittas, då stoppar JVM programmet och visar stackspårningen ( den nuvarande stapeln med metodanrop), efter att först ha utfört finally blocket om det finns. Exempel på undantagshantering:

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("-----------------");
        }

    }
    }
Här är resultaten av huvudmetoden :

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...
-----------------
Finalen används vanligtvis för att stänga alla strömmar och frigöra alla resurser som öppnas/tilldelas i ett försöksblock . Men när man skriver ett program är det inte alltid möjligt att hålla reda på stängningen av alla resurser. För att göra våra liv enklare erbjuder Javas utvecklare konstruktionen prova med resurser, som automatiskt stänger alla resurser som öppnas i ett försöksblock . Vårt första exempel kan skrivas om med prova-med-resurser :

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;
}
Tack vare Java-funktioner som introducerades i version 7 kan vi också kombinera fånga heterogena undantag i ett block, vilket gör koden mer kompakt och läsbar. Exempel:

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;
}

Poängen

Genom att använda undantag i Java kan du göra dina program mer robusta genom att skapa "backup-rutter", använda catch-blocks för att separera huvudkoden från undantagshanteringskoden och använda kast för att flytta ansvaret för undantagshanteringen till den som använder din metod .
Kommentarer
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION