Hvordan håndtere Java -unntak på riktig måte

Hvordan håndtere Java -unntak på riktig måte

Som programmering nybegynner, begrepet avvikshåndtering kan være vanskelig å vikle hodet rundt. Ikke at selve konseptet er vanskelig, men terminologien kan få det til å virke mer avansert enn det er. Og det er en så kraftig funksjon at det er utsatt for misbruk og misbruk.





I denne artikkelen lærer du hva unntak er, hvorfor de er viktige, hvordan du bruker dem og vanlige feil du bør unngå. De fleste moderne språk har en slags unntakshåndtering, så hvis du noen gang går videre fra Java, kan du ta de fleste av disse tipsene med deg.





Forstå Java -unntak

I Java, en unntak er et objekt som indikerer at noe unormalt (eller 'eksepsjonelt') skjedde under programmets kjøring. Slike unntak er kastet , som i utgangspunktet betyr at et unntaksobjekt er opprettet (i likhet med hvordan feil blir 'hevet').





Det fine er at du kan å fange kastede unntak, som lar deg håndtere den unormale tilstanden og la appen din fortsette å kjøre som om ingenting gikk galt. For eksempel, mens en nullpeker i C kan krasje applikasjonen din, lar Java deg kaste og fange

NullPointerException

s før en nullvariabel har en sjanse til å forårsake et krasj.



Husk at et unntak bare er et objekt, men med en viktig egenskap: det må forlenges fra

Exception

klasse eller en hvilken som helst underklasse av





Exception

. Selv om Java har alle slags innebygde unntak, kan du også lage dine egne hvis du ønsker det. Noen av de vanligste Java -unntakene inkludere:

  • NullPointerException
  • NumberFormatException
  • IllegalArgumentException
  • RuntimeException
  • IllegalStateException

Så hva skjer når du kaster et unntak?





Først ser Java på den umiddelbare metoden for å se om det er kode som håndterer typen unntak du kastet. Hvis en håndterer ikke eksisterer, ser den på metoden som kalte den nåværende metoden for å se om det finnes et håndtak der. Hvis ikke, ser det på metoden som ringte at metode, og deretter den neste metoden, etc. Hvis unntaket ikke blir fanget, skriver programmet ut en stabelsporing og krasjer deretter. (Egentlig er det mer nyansert enn bare å krasje, men det er et avansert tema utenfor denne artikkelen.)

TIL stabelspor er en liste over alle metodene Java kjørte gjennom mens de lette etter en unntaksbehandler. Slik ser et stabelspor ut:

Exception in thread 'main' java.lang.NullPointerException
at com.example.myproject.Book.getTitle(Book.java:16)
at com.example.myproject.Author.getBookTitles(Author.java:25)
at com.example.myproject.Bootstrap.main(Bootstrap.java:14)

Vi kan hente mye ut av dette. For det første var det kastede unntaket a

NullPointerException

. Det skjedde i

getTitle()

metode på linje 16 i Book.java. Den metoden ble kalt fra

getBookTitles()

på linje 25 i Author.java. At metoden ble kalt fra

main()

på linje 14 i Bootstrap.java. Som du kan se, gjør det enklere å feilsøke å vite alt dette.

Men igjen, den sanne fordelen med unntak er at du kan 'håndtere' den unormale tilstanden ved å fange unntaket, gjøre ting riktig og gjenoppta programmet uten å krasje.

Bruke Java -unntak i kode

La oss si at du har

someMethod()

som tar et helt tall og utfører en logikk som kan bryte hvis heltallet er mindre enn 0 eller større enn 100. Dette kan være et godt sted å kaste et unntak:

beste gratis radioapp for iphone
public void someMethod(int value) {
if (value 100) {
throw new
IllegalArgumentException

For å fange dette unntaket, må du gå dit

someMethod()

kalles og bruker prøve-fang-blokk :

public void callingMethod() {
try {
someMethod(200);
someOtherMethod();
} catch (IllegalArgumentException e) {
// handle the exception in here
}
// ...
}

Alt innenfor prøve blokken utføres i rekkefølge til et unntak kastes. Så snart et unntak kastes, hoppes alle påfølgende uttalelser og applikasjonslogikken hopper umiddelbart til å fange blokkere.

I vårt eksempel går vi inn på prøveblokken og ringer umiddelbart

someMethod()

. Siden 200 ikke er mellom 0 og 100, og

IllegalArgumentException

blir kastet. Dette avslutter umiddelbart henrettelsen av

someMethod()

, hopper over resten av logikken i prøveblokken (

someOtherMethod()

blir aldri kalt), og fortsetter utførelsen i fangstblokken.

Hva ville skje hvis vi ringte

someMethod(50)

i stedet? De

IllegalArgumentException

ville aldri bli kastet.

someMethod()

ville kjøre som normalt. Prøvblokken vil utføres som normalt, ringe

someOtherMethod()

når someMethod () er fullført. Når

someOtherMethod()

ender, ville fangstblokken bli hoppet over og

callingMethod()

ville fortsette.

Vær oppmerksom på at du kan ha flere fangstblokker per prøveblokk:

public void callingMethod() {
try {
someMethod(200);
someOtherMethod();
} catch (IllegalArgumentException e) {
// handle the exception in here
} catch (NullPointerException e) {
// handle the exception in here
}
// ...
}

Vær også oppmerksom på at det er valgfritt endelig blokken finnes også:

public void method() {
try {
// ...
} catch (Exception e) {
// ...
} finally {
// ...
}
}

Koden i en endelig blokk er bestandig henrettet uansett. Hvis du har en returoppgave i prøveblokken, blir den siste blokken utført før du går tilbake fra metoden. Hvis du kaster et annet unntak i fangstblokken, blir den siste blokken utført før unntaket kastes.

Du bør bruke den siste blokken når du har objekter som må ryddes opp før metoden slutter. For eksempel, hvis du åpnet en fil i prøveblokken og senere kastet et unntak, lar den siste blokken deg lukke filen før du forlater metoden.

Vær oppmerksom på at du kan ha en endelig blokk uten fangstblokk:

public void method() {
try {
// ...
} finally {
// ...
}
}

Dette lar deg gjøre nødvendig opprydding mens du tillater kastede unntak for å spre metodeanropsstakken (dvs. du vil ikke håndtere unntaket her, men du må fortsatt rydde opp først).

Sjekket mot Ukontrollerte unntak i Java

I motsetning til de fleste språk, skiller Java mellom sjekket unntak og ukontrollerte unntak (f.eks. C# har bare ukontrollerte unntak). Et kontrollert unntak bli fanget i metoden der unntaket kastes, ellers vil ikke koden kompilere.

For å opprette et merket unntak, strekker du fra

Exception

. For å opprette et ukontrollert unntak, strekker du fra

RuntimeException

.

Enhver metode som kaster et kontrollert unntak må markere dette i metodesignaturen ved hjelp av kaster søkeord. Siden Java er innebygd

IOException

er et kontrollert unntak, vil følgende kode ikke kompilere:

public void wontCompile() {
// ...
if (someCondition) {
throw new IOException();
}
// ...
}

Du må først erklære at den gir et kontrollert unntak:

public void willCompile() throws IOException {
// ...
if (someCondition) {
throw new IOException();
}
// ...
}

Vær oppmerksom på at en metode kan erklæres som å kaste et unntak, men aldri kaste et unntak. Likevel må unntaket fremdeles fanges, ellers vil ikke koden kompilere.

Når bør du bruke sjekkede eller ukontrollerte unntak?

Den offisielle Java -dokumentasjonen har en side om dette spørsmålet . Det oppsummerer forskjellen med en kortfattet tommelfingerregel: 'Hvis en klient med rimelighet kan forventes å komme seg etter et unntak, gjør den til et kontrollert unntak. Hvis en klient ikke kan gjøre noe for å komme seg fra unntaket, gjør det til et ukontrollert unntak. '

Men denne retningslinjen kan være utdatert. På den ene siden resulterer kontrollerte unntak i mer robust kode. På den annen side har ingen andre språk kontrollert unntak på samme måte som Java, som viser to ting: Den ene, funksjonen er ikke nyttig nok til at andre språk kan stjele den, og to, du kan absolutt leve uten dem. I tillegg spiller ikke kontrollerte unntak pent med lambda -uttrykk introdusert i Java 8.

Retningslinjer for bruk av Java -unntak

Unntak er nyttig, men lett misbrukt og misbrukt. Her er noen tips og gode fremgangsmåter for å unngå å lage rot i dem.

  • Foretrekker spesifikke unntak fremfor generelle unntak. Bruk | _+_ | over | _+_ | hvis mulig, bruk | _+_ | over | _+_ | når mulig.
  • Aldri fange | _+_ | ! Den | _+_ | klasse strekker seg faktisk | _+_ | , og fangstblokken fungerer faktisk med | _+_ | eller hvilken som helst klasse som strekker seg Throwable. Imidlertid | _+_ | klasse strekker seg også | _+_ | , og du vil aldri fange en | _+_ | fordi | _+_ | s indikerer alvorlige uopprettelige problemer.
  • Aldri fange | _+_ | ! | _+_ | strekker seg | _+_ | , så enhver blokk som fanger | _+_ | vil også fange | _+_ | , og det er et veldig viktig unntak som du ikke vil rote med (spesielt i applikasjoner med flere tråder) med mindre du vet hva du gjør. Hvis du ikke vet hvilket unntak du skal fange i stedet, bør du vurdere å ikke fange noe.
  • Bruk beskrivende meldinger for å lette feilsøking. Når du kaster et unntak, kan du oppgi en | _+_ | melding som et argument. Denne meldingen kan nås i fangstblokken ved hjelp av | _+_ | metode, men hvis unntaket aldri blir fanget, vil meldingen også vises som en del av stabelsporet.
  • Prøv å ikke fange og ignorere unntak. For å unngå ulempen med kontrollerte unntak, vil mange nybegynnere og late programmerere sette opp en fangstblokk, men la den stå tom. Dårlig! Behandle det alltid grasiøst, men hvis du ikke kan, kan du i det minste skrive ut et stabelspor slik at du vet at unntaket ble kastet. Du kan gjøre dette ved å bruke | _+_ | metode.
  • Vær forsiktig med å bruke for mange unntak. Når du har en hammer, ser alt ut som en spiker. Når du først lærer om unntak, kan du føle deg forpliktet til å gjøre alt til et unntak ... til det punktet der mesteparten av programmets kontrollflyt kommer til unntakshåndtering. Husk at unntak er ment for 'eksepsjonelle' hendelser!

Nå bør du være komfortabel nok med unntak til å forstå hva de er, hvorfor de brukes og hvordan du kan inkludere dem i din egen kode. Hvis du ikke helt forstår konseptet, er det greit! Det tok meg en stund før det 'klikket' i hodet mitt, så ikke føler at du trenger å skynde det. Ta den tiden du trenger.

Har du spørsmål? Vet du om noen andre unntaksrelaterte tips som jeg savnet? Del dem i kommentarene nedenfor!

Dele Dele kvitring E -post Hvordan lage et datastrømningsdiagram for å visualisere data fra ethvert prosjekt

Datastrømningsdiagrammer (DFD) for enhver prosess hjelper deg å forstå hvordan data flyter fra kilden til destinasjonen. Slik lager du det!

Les neste
Relaterte temaer
  • Programmering
  • Java
Om forfatteren Joel lee(1524 artikler publisert)

Joel Lee er sjefredaktør for MakeUseOf siden 2018. Han har en B.S. i informatikk og over ni års profesjonell skrive- og redigeringserfaring.

disk pigger til 100 windows 10
Mer fra Joel Lee

Abonner på vårt nyhetsbrev

Bli med i vårt nyhetsbrev for tekniske tips, anmeldelser, gratis ebøker og eksklusive tilbud!

Klikk her for å abonnere