1. Undtagelser
>
Langt om længe tænkte programmører på at standardisere og automatisere fejlhåndtering. Dette skete, da undtagelserne blev opfundet. Nu håndterer undtagelsesmekanismen 80 % af de ekstraordinære situationer.
Hvis en forsker fandt på undtagelser, var det sandsynligvis emnet for hans eller hendes doktorafhandling. Hvis en programmør fandt på det, så har han måske fået et venligt skulderklap fra en kollega: "Det virker okay, bro."
Når der opstår en fejl i et Java-program, såsom division med 0
, sker der nogle vidunderlige ting:
Trin et
Der oprettes et særligt undtagelsesobjekt, som indeholder information om den opståede fejl.
Alt i Java er et objekt, og undtagelser er ingen undtagelser 🙂 Undtagelsesobjekter har deres egne klasser, og det eneste der adskiller dem fra almindelige klasser er, at de arver klassen Throwable
.
Trin to
Undtagelsesobjektet er "smidt". Måske kunne formuleringen her være bedre. "At kaste en undtagelse" er mere som at udløse en brandalarm eller afgive en "DEFCON 1"-alarm.
Når der kastes en undtagelse til Java-maskinen, stopper den normale drift af programmet, og "nødprotokoller" begynder.
Trin tre
Metoden, hvor undtagelsen blev kastet, afsluttes med det samme. Undtagelsen overføres til opkaldsmetoden, som også afsluttes med det samme. Og så videre ned ad kæden, indtil main
metoden afsluttes. Når main
metoden afsluttes, gør programmet det også.
Eksempel:
Kode | Konsoludgang |
---|---|
|
|
En undtagelse opstår på linje 20: division med 0. Java-maskinen opretter straks en undtagelse — et ArithmeticException
objekt og "smider" det til metoden.
Metoden divide()
slutter med det samme, så vi ser aldrig strengen: Der skete ikke noget forfærdeligt: 0. Programmet vender tilbage til metoden endTheWorld()
, og situationen gentager sig: der er en uhåndteret undtagelse i systemet, hvilket betyder, at metoden endTheWorld()
også afsluttes unormalt. Derefter main
afsluttes metoden, og programmet stopper.
Hvad er formålet med disse undtagelser? Nå, du kan skrive din egen kode for at fange bestemte typer undtagelser og skrive din egen logik til at håndtere exceptionelle situationer.
2. Fangeundtagelser:try-catch
Java har en undtagelsesfangstmekanisme, der lader dig stoppe denne unormale afslutning af metoder. Det ser sådan ud:
try
{
// Code where an exception might occur
}
catch(ExceptionType name)
{
// Exception handling code
}
Denne konstruktion kaldes en try-catch
blok.
Koden, hvor der kan forekomme undtagelser , er pakket ind i krøllede klammeparenteser efter ordet try
.
Efter de krøllede klammeparenteser har vi nøgleordet catch
og inden for parentes erklæringen af en undtagelsesvariabel . Dette efterfølges af krøllede klammeparenteser, der ombryder koden, der skal udføres, hvis der opstår en undtagelse af den angivne type .
Hvis der ikke kastes undtagelser under udførelse af den " primære kode ", vil koden inde i catch-blokken ikke blive eksekveret. Hvis der opstår en undtagelse, så vil den være det (hvis typen af den kastede undtagelse er den samme som typen af variablen i parentes).
Eksempel:
Kode | Konsoludgang |
---|---|
|
|
3. Flere catch
blokke
I teorien kan alle mulige undtagelser smides i en kodeblok. Nogle vil du gerne håndtere på den ene måde, andre på en anden måde, og atter andre vil du beslutte dig for slet ikke at håndtere.
Java-udviklere besluttede at hjælpe dig og lade dig skrive ikke én, men mange catch
blokke efter try
blokeringen.
try
{
// Code where an exception might occur
}
catch (ExceptionType1 name1)
{
// Code for handling ExceptionType1
}
catch (ExceptionType2 name2)
{
// Code for handling ExceptionType2
}
catch (ExceptionType3 name3)
{
// Code for handling ExceptionType3
}
Eksempel:
Kode | Konsoludgang |
---|---|
|
|
4. Rækkefølge af catch
blokke
Undtagelser, der forekommer i en try
blok, kan kun fanges af en enkelt catch
blok. Du kan ikke have en undtagelseshåndteringssituation, hvor koden fra flere catch
blokke bliver eksekveret.
Men rækkefølgen af blokkene har betydning.
Du kan have en situation, hvor en undtagelse kan blive fanget af flere blokke. Hvis det er tilfældet, vil undtagelsen blive fanget af den catch- blok, der kommer først (tættest på try
blokken).
Hvordan kan du have en situation, hvor flere catch-blokke kan fange den samme undtagelse?
Alle undtagelser tilhører et enkelt arvehierarki - se diagrammet.
Et ArithmeticException
objekt kan tildeles til en variabel, hvis type er ArithmeticException
eller en af dens forfaderklasser: RuntimeException
, Exception
og Throwable
— se diagrammet.
Vi vil tale mere om arv og forfædreklasser på niveau 21.
Denne kode vil kompilere fint:
Fordele ved arv: |
---|
|
Så du kan fange en ArithmeticException
med enhver af de 4 catch
blokke ovenfor.
Eksempel 1:
Kode | Konsoludgang |
---|---|
|
|
I dette eksempel ArithmeticException
kan den fanges af både blokkene catch (Exception e)
og catch (ArithmeticException e)
. Det vil blive fanget af blokken tættest på blokken try
- den første catch
blok.
For at undgå overraskelser er det bedst at placere catch
blokke, der kan fange næsten enhver undtagelse nær slutningen af listen over catch
blokke.
Typen Throwable
er generelt i stand til at fange enhver mulig undtagelse i Java . Hvis du sætter den i den første catch
blok, så kompilerer koden ikke, da compileren ved, at der er kodeblokke, der ikke kan nås.