Java-unntak er bibliotektyper og språkfunksjoner som brukes til å representere og håndtere programfeil. Hvis du har ønsket å forstå hvordan feil er representert i kildekoden, har du kommet til rett sted. I tillegg til en oversikt over Java-unntak, vil jeg komme i gang med Java sine språkfunksjoner for å kaste objekter, prøve kode som kan mislykkes, fange kastede gjenstander og rydde opp Java-koden etter at et unntak er kastet.
I første halvdel av denne opplæringen lærer du om grunnleggende språkfunksjoner og bibliotektyper som har eksistert siden Java 1.0. I andre halvdel vil du oppdage avanserte funksjoner introdusert i nyere Java-versjoner.
Merk at kodeeksempler i denne opplæringen er kompatible med JDK 12.
last ned Få koden Last ned kildekoden for eksempel applikasjoner i denne opplæringen. Skapt av Jeff Friesen for JavaWorld.Hva er Java-unntak?
Feil oppstår når et Java-programs normale oppførsel blir avbrutt av uventet oppførsel. Denne avviket er kjent som en unntak. For eksempel prøver et program å åpne en fil for å lese innholdet, men filen eksisterer ikke. Java klassifiserer unntak i noen få typer, så la oss vurdere hvert enkelt.
Sjekket unntak
Java klassifiserer unntak som oppstår fra eksterne faktorer (for eksempel en manglende fil) som sjekket unntak. Java-kompilatoren sjekker at slike unntak er det håndtert (korrigert) der de oppstår eller er dokumentert for å bli håndtert andre steder.
Unntakshåndterere
An unntakshåndterer er en sekvens med kode som håndterer et unntak. Det avhører konteksten - noe som betyr at den leser verdier som er lagret fra variabler som var i omfang på det tidspunktet unntaket skjedde - og bruker deretter det den lærer å gjenopprette Java-programmet til en strøm av normal oppførsel. For eksempel kan en unntaksbehandler lese et lagret filnavn og be brukeren om å erstatte den manglende filen.
Runtime (ukontrollerte) unntak
Anta at et program prøver å dele et heltall med heltall 0. Denne umuligheten illustrerer en annen slags unntak, nemlig a kjøretid unntak. I motsetning til sjekket unntak, oppstår unntak for kjøretid vanligvis fra dårlig skrevet kildekode, og bør derfor løses av programmereren. Fordi kompilatoren ikke sjekker at unntak for kjøretid håndteres eller dokumenteres for å bli håndtert andre steder, kan du tenke på et unntak for kjøretid som et ukontrollert unntak.
Om unntak for kjøretid
Du kan endre et program for å håndtere et unntak for kjøretid, men det er bedre å fikse kildekoden. Runtime-unntak oppstår ofte fra å overføre ugyldige argumenter til et biblioteks metoder; buggy-koden skal være løst.
Feil
Noen unntak er veldig alvorlige fordi de bringer et programs evne til å fortsette utførelsen i fare. For eksempel prøver et program å tildele minne fra JVM, men det er ikke nok ledig minne til å tilfredsstille forespørselen. En annen alvorlig situasjon oppstår når et program prøver å laste en klassefil via en Class.forName ()
metodeanrop, men klassefilen er korrupt. Denne typen unntak er kjent som en feil. Du bør aldri prøve å håndtere feil selv, fordi JVM kanskje ikke kan komme seg fra den.
Unntak i kildekoden
Et unntak kan vises i kildekoden som et feil kode eller som en gjenstand. Jeg introduserer begge deler og viser deg hvorfor gjenstander er overlegne.
Feilkoder versus objekter
Programmeringsspråk som C bruker heltalsbasert feilkoder å representere svikt og årsaker til svikt - dvs. unntak. Her er et par eksempler:
hvis (chdir ("C: \ temp")) printf ("Kan ikke endre til tempkatalog:% d \ n", errno); FIL * fp = fopen ("C: \ temp \ foo"); if (fp == NULL) printf ("Kan ikke åpne foo:% d \ n", errno);
C-er chdir ()
(endre katalog) -funksjonen returnerer et helt tall: 0 ved suksess eller -1 ved feil. Tilsvarende C fopen ()
(fil åpen) -funksjonen returnerer en null pekeren (heltall adresse) til a FIL
struktur på suksess eller en null (0) peker (representert med konstant NULL
) på feil. I begge tilfeller må du lese det globale for å identifisere unntaket som forårsaket feilen errno
variabels heltallbaserte feilkode.
Feilkoder gir noen problemer:
- Heltall er meningsløst; de beskriver ikke unntakene de representerer. Hva betyr for eksempel 6?
- Å knytte sammenheng med en feilkode er vanskelig. For eksempel vil du kanskje sende navnet på filen som ikke kunne åpnes, men hvor skal du lagre filnavnet?
- Heltall er vilkårlig, noe som kan føre til forvirring når du leser kildekoden. For eksempel å spesifisere
hvis (! chdir ("C: \ temp"))
(!
betyr IKKE) i stedet forhvis (chdir ("C: \ temp"))
å teste for feil er tydeligere. Imidlertid ble 0 valgt for å indikere suksess, og såhvis (chdir ("C: \ temp"))
må spesifiseres for å teste for feil. - Feilkoder er for enkle å ignorere, noe som kan føre til feilkode. For eksempel kan programmereren spesifisere
chdir ("C: \ temp");
og ignorerehvis (fp == NULL)
Sjekk. Videre trenger ikke programmereren å undersøkeerrno
. Ved ikke å teste for feil, oppfører programmet seg uberegnelig når en av funksjonene returnerer en feilindikator.
For å løse disse problemene omfavnet Java en ny tilnærming til unntakshåndtering. I Java kombinerer vi objekter som beskriver unntak med en mekanisme basert på å kaste og fange disse objektene. Her er noen fordeler ved å bruke objekter versus feilkode for å betegne unntak:
- Et objekt kan opprettes fra en klasse med et meningsfylt navn. For eksempel,
FileNotFoundException
(ijava.io
pakke) er mer meningsfull enn 6. - Objekter kan lagre kontekst i forskjellige felt. For eksempel kan du lagre en melding, navnet på filen som ikke kunne åpnes, den siste posisjonen der en analyseoperasjon mislyktes, og / eller andre elementer i et objekts felt.
- Du bruker ikke
hvis
uttalelser for å teste for feil. I stedet kastes unntaksobjekter til en behandler som er skilt fra programkoden. Som et resultat er kildekoden lettere å lese og mindre sannsynlig å være buggy.
Kastbar og dens underklasser
Java gir et hierarki av klasser som representerer forskjellige typer unntak. Disse klassene er forankret i java.lang
pakken er Kastbar
klasse, sammen med sin Unntak
, RuntimeException
, og Feil
underklasser.
Kastbar
er den ultimate superklassen når det gjelder unntak. Bare gjenstander opprettet fra Kastbar
og dens underklasser kan kastes (og deretter fanges). Slike gjenstander er kjent som kasteutstyr.
EN Kastbar
objekt er assosiert med en detaljmelding som beskriver et unntak. Flere konstruktører, inkludert paret beskrevet nedenfor, er gitt for å lage en Kastbar
objekt med eller uten detaljmelding:
- Kastbar () skaper en
Kastbar
uten detaljmelding. Denne konstruktøren passer for situasjoner der det ikke er noen sammenheng. For eksempel vil du bare vite at en bunke er tom eller full. - Kastbar (strengmelding) skaper en
Kastbar
medbeskjed
som detaljmeldingen. Denne meldingen kan sendes til brukeren og / eller logges.
Kastbar
gir den String getMessage ()
metode for å returnere detaljmeldingen. Det gir også flere nyttige metoder, som jeg vil introdusere senere.
Unntaksklassen
Kastbar
har to direkte underklasser. En av disse underklassene er Unntak
, som beskriver et unntak som oppstår fra en ekstern faktor (for eksempel å prøve å lese fra en ikke-eksisterende fil). Unntak
erklærer de samme konstruktørene (med identiske parameterlister) som Kastbar
, og hver konstruktør påberoper seg Kastbar
motstykke. Unntak
arver Kastbar
sine metoder; den erklærer ingen nye metoder.
Java tilbyr mange unntaksklasser som direkte underklasser Unntak
. Her er tre eksempler:
- CloneNotSupportedException signaliserer et forsøk på å klone et objekt hvis klasse ikke implementerer
Klonbar
grensesnitt. Begge typene er ijava.lang
pakke. - IO Unntak signaliserer at det har oppstått en slags I / O-feil. Denne typen ligger i
java.io
pakke. - ParseException signaliserer at det har oppstått en feil under parsing av tekst. Denne typen finnes i
java.text
pakke.
Legg merke til at hver Unntak
underklassens navn ender med ordet Unntak
. Denne konvensjonen gjør det enkelt å identifisere klassens formål.
Du vil vanligvis underklasse Unntak
(eller en av underklassene) med dine egne unntaksklasser (hvis navn skal slutte med Unntak
). Her er et par egendefinerte underklasseeksempler:
offentlig klasse StackFullException utvider unntak {} offentlig klasse EmptyDirectoryException utvider unntak {private String directoryName; offentlig EmptyDirectoryException (strengmelding, streng katalognavn) {super (melding); this.directoryName = katalognavn; } offentlig streng getDirectoryName () {return katalognavn; }}
Det første eksemplet beskriver en unntaksklasse som ikke krever detaljmelding. Det er standard noargument-konstruktør påberoper seg Unntak()
, som påberoper seg Kastbar ()
.
Det andre eksemplet beskriver en unntaksklasse hvis konstruktør krever en detaljmelding og navnet på den tomme katalogen. Konstruktøren påberoper seg Unntak (strengmelding)
, som påberoper seg Kastbar (strengmelding)
.
Objekter instantiert fra Unntak
eller en av underklassene (unntatt RuntimeException
eller en av underklassene) er sjekket unntak.
RuntimeException-klassen
Unntak
er direkte underklassert av RuntimeException
, som beskriver et unntak som mest sannsynlig oppstår fra dårlig skrevet kode. RuntimeException
erklærer de samme konstruktørene (med identiske parameterlister) som Unntak
, og hver konstruktør påberoper seg Unntak
motstykke. RuntimeException
arver Kastbar
sine metoder. Den erklærer ingen nye metoder.
Java tilbyr mange unntaksklasser som direkte underklasser RuntimeException
. Følgende eksempler er alle medlemmer av java.lang
pakke:
- Aritmetisk unntak signaliserer en ulovlig aritmetisk operasjon, for eksempel å prøve å dele et heltall med 0.
- IllegalArgumentException signaliserer at et ulovlig eller upassende argument har blitt overført til en metode.
- NullPointerException signaliserer et forsøk på å påkalle en metode eller få tilgang til et forekomstfelt via nullreferansen.
Objekter instantiert fra RuntimeException
eller en av dens underklasser er ukontrollerte unntak.
Feilklassen
Kastbar
sin andre direkte underklasse er Feil
, som beskriver et alvorlig (til og med unormalt) problem som en fornuftig applikasjon ikke skal prøve å håndtere - for eksempel å gå tom for minne, overfylle JVM-stakken eller prøve å laste en klasse som ikke blir funnet. Som Unntak
, Feil
erklærer identiske konstruktører til Kastbar
, arver Kastbar
sine metoder, og erklærer ikke noen av sine egne metoder.
Du kan identifisere deg Feil
underklasser fra konvensjonen som klassenavnene deres slutter med Feil
. Eksempler inkluderer OutOfMemoryError
, LinkageError
, og StackOverflowError
. Alle tre typene tilhører java.lang
pakke.
Kaster unntak
En C-biblioteksfunksjon varsler anropskoden om et unntak ved å angi den globale errno
variabel til en feilkode og returnere en feilkode. Derimot kaster en Java-metode et objekt. Å vite hvordan og når man skal kaste unntak er et viktig aspekt av effektiv Java-programmering. Å kaste et unntak innebærer to grunnleggende trinn:
- Bruke
kaste
uttalelse for å kaste et unntaksobjekt. - Bruke
kaster
klausul for å informere kompilatoren.
Senere seksjoner vil fokusere på å fange unntak og rydde opp etter dem, men la oss først lære mer om kastevarer.
Kasterklæringen
Java tilbyr kaste
uttalelse for å kaste et objekt som beskriver et unntak. Her er syntaksen til kaste
uttalelse:
kaste kastbar;
Objektet identifisert av kastbar
er en forekomst av Kastbar
eller noen av underklassene. Imidlertid kaster du vanligvis bare gjenstander instantiert fra underklasser av Unntak
eller RuntimeException
. Her er et par eksempler:
kaste ny FileNotFoundException ("finner ikke fil" + filnavn); kaste nye IllegalArgumentException ("argumentet overført til telling er mindre enn null");
Kastbar kastes fra den nåværende metoden til JVM, som sjekker denne metoden for en passende handler. Hvis den ikke blir funnet, avvikler JVM metoden samtalestakken og ser etter den nærmeste anropsmetoden som kan håndtere unntaket beskrevet av kastet. Hvis den finner denne metoden, overføres den kastbar til metodens håndterer, hvis kode blir utført for å håndtere unntaket. Hvis det ikke finnes noen metode for å håndtere unntaket, avsluttes JVM med en passende melding.
Kast-klausulen
Du må informere kompilatoren når du kaster et avkrysset unntak ut av en metode. Gjør dette ved å legge til en kaster
klausul til metodens overskrift. Denne paragrafen har følgende syntaks:
kaster checkedExceptionClassName (, checkedExceptionClassName)*
EN kaster
klausul består av nøkkelord kaster
etterfulgt av en kommaseparert liste over klassenavnene på avmerkede unntak kastet ut av metoden. Her er et eksempel:
public static void main (String [] args) kaster ClassNotFoundException {if (args.length! = 1) {System.err.println ("bruk: java ... classfile"); komme tilbake; } Class.forName (args [0]); }
Dette eksemplet prøver å laste inn en klassefil som er identifisert av et kommandolinjeargument. Hvis Class.forName ()
finner ikke klassefilen, kaster den en java.lang.ClassNotFoundException
objekt, som er et sjekket unntak.
Sjekket unntakskontrovers
De kaster
klausul og sjekket unntak er kontroversielle. Mange utviklere hater å bli tvunget til å spesifisere kaster
eller håndter det avmerkede unntaket. Lær mer om dette fra min. Er avmerkede unntak gode eller dårlige? blogg innlegg.