1. Typer av undantag

Alla undantag är indelade i 4 typer, som faktiskt är klasser som ärver varandra.
Throwable
klass
Basklassen för alla undantag är Throwable
klassen. Klassen Throwable
innehåller koden som skriver den aktuella anropsstacken (stackspårning av den aktuella metoden) till en array. Vi kommer att lära oss vad en stackspårning är lite senare.
Kastoperatören kan bara acceptera ett objekt som härrör från klassen . Throwable
Och även om du teoretiskt sett kan skriva kod som throw new Throwable();
, brukar ingen göra detta. Huvudsyftet med Throwable
klassen är att ha en ensamförälderklass för alla undantag.
Error
klass
Nästa undantagsklass är Error
klassen, som direkt ärver Throwable
klassen. Java-maskinen skapar objekt av Error
klassen (och dess avkomlingar) när allvarliga problem har uppstått . Till exempel ett hårdvarufel, otillräckligt minne, etc.
Vanligtvis, som programmerare, finns det inget du kan göra i en situation där ett sådant fel (den typ som en Error
ska kastas för) har inträffat i programmet: dessa fel är för allvarliga. Allt du kan göra är att meddela användaren att programmet kraschar och/eller skriva all känd information om felet till programloggen.
Exception
klass
Klasserna Exception
och RuntimeException
är för vanliga fel som inträffar i driften av många metoder. Målet med varje kastat undantag är att fångas av ett catch
block som vet hur det ska hanteras på rätt sätt.
När en metod av någon anledning inte kan slutföra sitt arbete, bör den omedelbart meddela anropsmetoden genom att kasta ett undantag av lämplig typ.
Med andra ord, om en variabel är lika med null
, kommer metoden att kasta en NullPointerException
. Om de felaktiga argumenten skickades till metoden kommer den att kasta en InvalidArgumentException
. Om metoden av misstag delar sig med noll, kommer den att kasta en ArithmeticException
.
RuntimeException
klass
RuntimeExceptions
är en delmängd av Exceptions
. Vi skulle till och med kunna säga att det RuntimeException
är en lätt version av vanliga undantag ( Exception
) — färre krav och begränsningar ställs på sådana undantag
Du kommer att lära dig skillnaden mellan Exception
och RuntimeException
senare.
2. Throws
: markerade undantag

Alla Java-undantag delas in i två kategorier: markerad och omarkerad .
Alla undantag som ärver RuntimeException
eller Error
anses vara okontrollerade undantag . Alla andra är markerade undantag .
Tjugo år efter att kontrollerade undantag infördes, ser nästan alla Java-programmerare på detta som en bugg. I populära moderna ramverk är 95 % av alla undantag avmarkerade. C#-språket, som nästan kopierade Java exakt, lade inte till markerade undantag .
Vad är den största skillnaden mellan markerade och omarkerade undantag?
Det finns ytterligare krav på kontrollerade undantag. Grovt sett är de dessa:
Krav 1
Om en metod kastar ett markerat undantag måste den ange typen av undantag i sin signatur . På så sätt är varje metod som anropar den medveten om att detta "meningsfulla undantag" kan förekomma i den.
Ange markerade undantag efter metodparametrarna efter throws
nyckelordet (använd inte throw
nyckelordet av misstag). Det ser ut ungefär så här:
type method (parameters) throws exception
Exempel:
kontrollerat undantag | okontrollerat undantag |
---|---|
|
|
I exemplet till höger ger vår kod ett omarkerat undantag – ingen ytterligare åtgärd krävs. I exemplet till vänster ger metoden ett markerat undantag, så throws
nyckelordet läggs till i metodsignaturen tillsammans med typen av undantag.
Om en metod förväntar sig att skapa flera markerade undantag måste alla anges efter throws
nyckelordet, avgränsade med kommatecken. Ordningen är inte viktig. Exempel:
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
Om du anropar en metod som har kontrollerat undantag i sin signatur kan du inte bortse från att den kastar dem.
Du måste antingen fånga alla sådana undantag genom att lägga till catch
block för var och en, eller genom att lägga till dem i en throws
sats för din metod.
Det är som om vi säger: " Dessa undantag är så viktiga att vi måste fånga dem. Och om vi inte vet hur vi ska hantera dem, då måste alla som kan anropa vår metod meddelas att sådana undantag kan förekomma i den.
Exempel:
Föreställ dig att vi skriver en metod för att skapa en värld befolkad av människor. Det initiala antalet personer skickas som ett argument. Så vi måste lägga till undantag om det är för få personer.
Skapar jorden | Notera |
---|---|
|
Metoden ger potentiellt två markerade undantag:
|
Detta metodanrop kan hanteras på tre sätt:
1. Fånga inga undantag
Detta görs oftast när metoden inte vet hur den ska hantera situationen på rätt sätt.
Koda | Notera |
---|---|
|
Anropsmetoden fångar inte upp undantagen och måste informera andra om dem: den lägger till dem i sin egen throws klausul |
2. Fånga några av undantagen
Vi hanterar de fel vi kan hantera. Men de vi inte förstår, vi kastar upp dem till anropsmetoden. För att göra detta måste vi lägga till deras namn till throws-satsen:
Koda | Notera |
---|---|
|
Den som ringer fångar bara ett markerat undantag — LonelyWorldException . Det andra undantaget måste läggas till i sin signatur, vilket anger det efter throws nyckelordet |
3. Fånga alla undantag
Om metoden inte ger undantag från anropsmetoden, är anropsmetoden alltid säker på att allt fungerade bra. Och det kommer inte att kunna vidta några åtgärder för att fixa en exceptionell situation.
Koda | Notera |
---|---|
|
Alla undantag fångas i denna metod. Den som ringer kommer att vara säker på att allt gick bra. |
3. Fånga flera undantag
Programmerare hatar verkligen att duplicera kod. De kom till och med på en motsvarande utvecklingsprincip — DRY : Don't Repeat Yourself. Men vid hantering av undantag finns det ofta tillfällen då ett try
block följs av flera catch
block med samma kod.
Eller det kan finnas 3 catch
block med samma kod och ytterligare 2 catch
block med annan identisk kod. Detta är en standardsituation när ditt projekt hanterar undantag på ett ansvarsfullt sätt.
Från och med version 7 lades i Java-språket till möjligheten att specificera flera typer av undantag i ett enda catch
block. Det ser ungefär ut så här:
try
{
// Code where an exception might occur
}
catch (ExceptionType1 | ExceptionType2 | ExceptionType3 name)
{
// Exception handling code
}
Du kan ha hur många catch
block du vill. Ett enda catch
block kan dock inte specificera undantag som ärver varandra. Du kan med andra ord inte skriva catch ( Exception
| RuntimeException
e), eftersom RuntimeException
klassen ärver Exception
.
GO TO FULL VERSION