1. Typer af undtagelser

Alle undtagelser er opdelt i 4 typer, som faktisk er klasser, der arver hinanden.
Throwable
klasse
Basisklassen for alle undtagelser er Throwable
klassen. Klassen Throwable
indeholder koden, der skriver den aktuelle opkaldsstak (staksporing af den aktuelle metode) til et array. Vi lærer, hvad et stakspor er lidt senere.
Kasteoperatøren kan kun acceptere et objekt, der stammer fra klassenThrowable
. Og selvom du teoretisk kan skrive kode som throw new Throwable();
, er der normalt ingen, der gør dette. Klassens hovedformål Throwable
er at have en enkeltforælderklasse for alle undtagelser.
Error
klasse
Den næste undtagelsesklasse er Error
klassen, som direkte arver Throwable
klassen. Java-maskinen opretter objekter af Error
klassen (og dens efterkommere), når der er opstået alvorlige problemer . For eksempel en hardwarefejl, utilstrækkelig hukommelse osv.
Normalt, som programmør, er der ikke noget, du kan gøre i en situation, hvor en sådan fejl (den slags, som en Error
skal kastes for) er opstået i programmet: disse fejl er for alvorlige. Det eneste du kan gøre er at give brugeren besked om, at programmet går ned og/eller skrive alle kendte oplysninger om fejlen til programloggen.
Exception
klasse
Klasserne Exception
og RuntimeException
er til almindelige fejl, der opstår i driften af mange metoder. Målet med hver kastet undtagelse er at blive fanget af en catch
blok, der ved, hvordan man håndterer den korrekt.
Når en metode af en eller anden grund ikke kan fuldføre sit arbejde, skal den straks underrette den kaldende metode ved at kaste en undtagelse af den passende type.
Med andre ord, hvis en variabel er lig med null
, vil metoden kaste en NullPointerException
. Hvis de forkerte argumenter blev sendt til metoden, vil den kaste en InvalidArgumentException
. Hvis metoden ved et uheld deler sig med nul, vil den kaste en ArithmeticException
.
RuntimeException
klasse
RuntimeExceptions
er en delmængde af Exceptions
. Vi kunne endda sige, at RuntimeException
det er en letvægtsversion af almindelige undtagelser ( Exception
) — færre krav og begrænsninger er pålagt sådanne undtagelser
Du vil lære forskellen mellem Exception
og RuntimeException
senere.
2. Throws
: kontrollerede undtagelser

Alle Java-undtagelser falder i 2 kategorier: markeret og umarkeret .
Alle undtagelser, der arver RuntimeException
eller Error
betragtes som ukontrollerede undtagelser . Alle andre er kontrollerede undtagelser .
Tyve år efter at kontrollerede undtagelser blev introduceret, opfatter næsten enhver Java-programmør dette som en fejl. I populære moderne rammer er 95% af alle undtagelser ikke markeret. C#-sproget, som næsten kopierede Java nøjagtigt, tilføjede ikke kontrollerede undtagelser .
Hvad er hovedforskellen mellem kontrollerede og ukontrollerede undtagelser?
Der stilles yderligere krav til kontrollerede undtagelser. Groft sagt er de disse:
Krav 1
Hvis en metode kaster en markeret undtagelse , skal den angive typen af undtagelse i sin signatur . På den måde er enhver metode, der kalder den, klar over, at denne "meningsfulde undtagelse" kan forekomme i den.
Angiv markerede undtagelser efter metodeparametrene efter throws
nøgleordet (brug ikke throw
nøgleordet ved en fejl). Det ser sådan ud:
type method (parameters) throws exception
Eksempel:
kontrolleret undtagelse | umarkeret undtagelse |
---|---|
|
|
I eksemplet til højre giver vores kode en umarkeret undtagelse - ingen yderligere handling er påkrævet. I eksemplet til venstre kaster metoden en markeret undtagelse, så throws
nøgleordet tilføjes til metodesignaturen sammen med typen af undtagelsen.
Hvis en metode forventer at kaste flere markerede undtagelser, skal alle angives efter throws
nøgleordet, adskilt af kommaer. Rækkefølgen er ikke vigtig. Eksempel:
public void calculate(int n) throws Exception, IOException
{
if (n == 0)
throw new Exception("n is null!");
if (n == 1)
throw new IOException("n is 1");
}
Krav 2
Hvis du kalder en metode, der har kontrolleret undtagelser i sin signatur, kan du ikke ignorere, at den kaster dem.
Du skal enten fange alle sådanne undtagelser ved at tilføje catch
blokke for hver enkelt, eller ved at tilføje dem til en throws
klausul for din metode.
Det er, som om vi siger: " Disse undtagelser er så vigtige, at vi må fange dem. Og hvis vi ikke ved, hvordan vi skal håndtere dem, så skal enhver, der måtte kalde vores metode, have besked om, at sådanne undtagelser kan forekomme i den.
Eksempel:
Forestil dig, at vi skriver en metode til at skabe en verden befolket af mennesker. Det oprindelige antal personer sendes som et argument. Så vi skal tilføje undtagelser, hvis der er for få mennesker.
At skabe Jorden | Bemærk |
---|---|
|
Metoden kaster potentielt to kontrollerede undtagelser:
|
Dette metodekald kan håndteres på 3 måder:
1. Fang ikke nogen undtagelser
Dette gøres oftest, når metoden ikke ved, hvordan man korrekt håndterer situationen.
Kode | Bemærk |
---|---|
|
Kaldmetoden fanger ikke undtagelserne og skal informere andre om dem: den føjer dem til sin egen throws klausul |
2. Fang nogle af undtagelserne
Vi håndterer de fejl, vi kan håndtere. Men dem, vi ikke forstår, kaster vi dem op til kaldemetoden. For at gøre dette skal vi tilføje deres navn til throws-klausulen:
Kode | Bemærk |
---|---|
|
Den, der ringer, fanger kun én markeret undtagelse — LonelyWorldException . Den anden undtagelse skal føjes til sin signatur, hvilket angiver den efter throws nøgleordet |
3. Fang alle undtagelser
Hvis metoden ikke kaster undtagelser fra den kaldende metode, så er den kaldende metode altid sikker på, at alt fungerede godt. Og det vil ikke være i stand til at foretage sig noget for at rette op på en usædvanlig situation.
Kode | Bemærk |
---|---|
|
Alle undtagelser er fanget i denne metode. Den, der ringer, vil være sikker på, at alt gik godt. |
3. Fange flere undtagelser
Programmører hader virkelig at duplikere kode. De kom endda med et tilsvarende udviklingsprincip — DRY : Don't Repeat Yourself. Men når du håndterer undtagelser, er der hyppige lejligheder, hvor en try
blok efterfølges af flere catch
blokke med samme kode.
Eller der kunne være 3 catch
blokke med samme kode og yderligere 2 catch
blokke med anden identisk kode. Dette er en standardsituation, når dit projekt håndterer undtagelser ansvarligt.
Startende med version 7 tilføjede Java-sproget muligheden for at specificere flere typer undtagelser i en enkelt catch
blok. Det ser nogenlunde sådan ud:
try
{
// Code where an exception might occur
}
catch (ExceptionType1 | ExceptionType2 | ExceptionType3 name)
{
// Exception handling code
}
Du kan have så mange catch
blokke, som du vil. En enkelt blok kan dog catch
ikke specificere undtagelser, der arver hinanden. Du kan med andre ord ikke skrive catch ( Exception
| RuntimeException
e), fordi RuntimeException
klassen arver Exception
.
GO TO FULL VERSION