Sådan håndteres Java -undtagelser på den rigtige måde

Sådan håndteres Java -undtagelser på den rigtige måde

Som programmering nybegynder, konceptet med undtagelseshåndtering kan være svært at vikle dit hoved rundt. Ikke at selve konceptet er svært, men terminologien kan få det til at virke mere avanceret end det er. Og det er så stærk en funktion, at den er tilbøjelig til misbrug og misbrug.





I denne artikel lærer du, hvad undtagelser er, hvorfor de er vigtige, hvordan du bruger dem og almindelige fejl, der skal undgås. De fleste moderne sprog har en eller anden form for undtagelseshåndtering, så hvis du nogensinde kommer videre fra Java, kan du tage de fleste af disse tips med dig.





Forståelse af Java -undtagelser

I Java, en undtagelse er et objekt, der angiver, at noget unormalt (eller 'usædvanligt') opstod under din applikations kørsel. Sådanne undtagelser er kastet , hvilket grundlæggende betyder, at der oprettes et undtagelsesobjekt (svarende til hvordan fejl 'hæves').





Skønheden er, at du kan fangst kastede undtagelser, som lader dig håndtere den unormale tilstand og tillader din applikation at fortsætte med at køre, som om intet gik galt. For eksempel, mens en nullemarkør i C kan gå ned på din applikation, lader Java dig kaste og fange

NullPointerException

s før en null -variabel har en chance for at forårsage et nedbrud.



Husk, at en undtagelse bare er et objekt, men med en vigtig egenskab: den skal forlænges fra

Exception

klasse eller en hvilken som helst underklasse af





Exception

. Mens Java har alle former for indbyggede undtagelser, kan du også oprette dine egne, hvis du ønsker det. Nogle af mest almindelige Java -undtagelser omfatte:

  • NullPointerException
  • NumberFormatException
  • IllegalArgumentException
  • RuntimeException
  • IllegalStateException

Så hvad sker der, når du kaster en undtagelse?





For det første ser Java inden for den umiddelbare metode for at se, om der er kode, der håndterer den slags undtagelse, du kastede. Hvis der ikke findes en handler, ser den på den metode, der kaldte den aktuelle metode for at se, om der findes et håndtag der. Hvis ikke, ser den på den metode, der kaldte at metode, og derefter den næste metode osv. Hvis undtagelsen ikke fanges, udskriver programmet en stacksporing og går derefter ned. (Faktisk er det mere nuanceret end bare at gå ned, men det er et avanceret emne uden for denne artikels omfang.)

TIL stackspor er en liste over alle de metoder, Java gennemgik, mens de ledte efter en undtagelseshandler. Sådan ser et stackspor ud:

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 meget ud af dette. For det første var den kastede undtagelse a

NullPointerException

. Det skete i

getTitle()

metode på linje 16 i Book.java. Den metode blev kaldt fra

getBookTitles()

på linje 25 i Author.java. At metode blev kaldt fra

main()

på linje 14 i Bootstrap.java. Som du kan se, gør kendskabet til alt dette lettere for fejlfinding.

Men igen, den sande fordel ved undtagelser er, at du kan 'håndtere' den unormale tilstand ved at fange undtagelsen, rette tingene og genoptage applikationen uden at gå ned.

Brug af Java -undtagelser i kode

Lad os sige, at du har

someMethod()

der tager et helt tal og udfører en eller anden logik, der kan bryde, hvis heltalet er mindre end 0 eller større end 100. Dette kan være et godt sted at kaste en undtagelse:

hvordan man får filer fra harddisken
public void someMethod(int value) {
if (value 100) {
throw new
IllegalArgumentException

For at fange denne undtagelse skal du gå til hvor

someMethod()

kaldes og bruge prøve-fang-blok :

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

Alt inden for prøve blok udføres i rækkefølge, indtil en undtagelse er kastet. Så snart en undtagelse kastes, springes alle efterfølgende udsagn over, og applikationslogikken springer straks til fangst blok.

I vores eksempel går vi ind i prøveblokken og ringer straks

someMethod()

. Da 200 ikke er mellem 0 og 100, vil en

IllegalArgumentException

bliver kastet. Dette afslutter straks udførelsen af

someMethod()

, springer resten af ​​logikken over i prøveblokken (

someOtherMethod()

kaldes aldrig), og genoptager udførelsen inden for fangstblokken.

Hvad ville der ske, hvis vi ringede

someMethod(50)

i stedet? Det

IllegalArgumentException

aldrig ville blive kastet.

someMethod()

ville køre som normalt. Prøvblokken udføres som normalt og ringer

someOtherMethod()

når someMethod () er fuldført. Hvornår

someOtherMethod()

ender, fangstblokken ville blive sprunget over og

callingMethod()

ville fortsætte.

Bemærk, at du kan have flere fangstblokke pr. Prøveblok:

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

Bemærk også, at en valgfri endelig blok findes også:

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

Koden inden for en endelig blok er altid henrettet uanset hvad. Hvis du har en returerklæring i prøveblokken, udføres den endelige blok, før du vender tilbage fra metoden. Hvis du kaster en anden undtagelse i fangstblokken, udføres den sidste blok før undtagelsen kastes.

Du skal bruge den endelige blok, når du har objekter, der skal ryddes op, før metoden slutter. For eksempel, hvis du åbnede en fil i prøveblokken og senere kastede en undtagelse, lader den endelige blok dig lukke filen, før du forlader metoden.

Bemærk, at du kan få en endelig blok uden en fangstblok:

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

Dette lader dig foretage enhver nødvendig oprydning, mens du tillader kastede undtagelser at sprede metoden til påkaldelse af stakken (dvs. du vil ikke håndtere undtagelsen her, men du skal stadig rydde op først).

Markeret kontra Ukontrollerede undtagelser i Java

I modsætning til de fleste sprog skelner Java mellem kontrollerede undtagelser og ukontrollerede undtagelser (f.eks. C# har kun ukontrollerede undtagelser). En kontrolleret undtagelse skal blive fanget i den metode, hvor undtagelsen kastes, ellers vil koden ikke kompilere.

For at oprette en markeret undtagelse skal du forlænge fra

Exception

. For at oprette en ukontrolleret undtagelse skal du strække dig fra

RuntimeException

.

Enhver metode, der kaster en markeret undtagelse, skal angive dette i metodesignaturen ved hjælp af kaster nøgleord. Siden Java er indbygget

IOException

er en markeret undtagelse, vil følgende kode ikke kompilere:

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

Du skal først erklære, at den kaster en markeret undtagelse:

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

Bemærk, at en metode kan erklæres for at kaste en undtagelse, men aldrig faktisk kaste en undtagelse. Alligevel skal undtagelsen stadig fanges, ellers vil koden ikke kompilere.

Hvornår skal du bruge kontrollerede eller ukontrollerede undtagelser?

Den officielle Java -dokumentation har en side om dette spørgsmål . Det opsummerer forskellen med en kortfattet tommelfingerregel: 'Hvis en klient med rimelighed kan forventes at komme sig efter en undtagelse, gør den til en kontrolleret undtagelse. Hvis en klient ikke kan gøre noget for at komme sig fra undtagelsen, gør den til en ukontrolleret undtagelse. '

Men denne retningslinje kan være forældet. På den ene side resulterer kontrollerede undtagelser i mere robust kode. På den anden side har intet andet sprog kontrolleret undtagelser på samme måde som Java, hvilket viser to ting: Den ene, funktionen er ikke nyttig nok til, at andre sprog stjæler den, og to, du kan absolut leve uden dem. Plus, kontrollerede undtagelser spiller ikke pænt med lambda -udtryk introduceret i Java 8.

Retningslinjer for brug af Java -undtagelser

Undtagelser er nyttige, men let misbrugte og misbrugte. Her er et par tips og bedste fremgangsmåder, der hjælper dig med at undgå at lave rod i dem.

  • Foretrækker specifikke undtagelser frem for generelle undtagelser. Brug | _+_ | over | _+_ | hvis det er muligt, brug ellers | _+_ | over | _+_ | når det er muligt.
  • Fang aldrig | _+_ | ! Den | _+_ | klasse strækker sig faktisk | _+_ | , og fangstblokken fungerer faktisk med | _+_ | eller enhver klasse, der strækker sig Kastbar. Imidlertid er | _+_ | klasse udvider også | _+_ | , og du vil aldrig fange en | _+_ | fordi | _+_ | s angiver alvorlige uoprettelige problemer.
  • Fang aldrig | _+_ | ! | _+_ | forlænger | _+_ | , så enhver blok, der fanger | _+_ | vil også fange | _+_ | , og det er en meget vigtig undtagelse, som du ikke vil rode med (især i applikationer med flere tråde), medmindre du ved, hvad du laver. Hvis du ikke ved, hvilken undtagelse du skal fange i stedet, skal du overveje ikke at fange noget.
  • Brug beskrivende meddelelser til at lette fejlfinding. Når du kaster en undtagelse, kan du angive en | _+_ | besked som argument. Denne meddelelse kan fås i fangstblokken ved hjælp af | _+_ | metode, men hvis undtagelsen aldrig bliver fanget, vises meddelelsen også som en del af stacksporet.
  • Prøv ikke at fange og ignorere undtagelser. For at komme uden om besværet med kontrollerede undtagelser, vil en masse nybegyndere og dovne programmører oprette en fangstblok, men lade den stå tom. Dårligt! Håndter det altid yndefuldt, men hvis du ikke kan, skal du i det mindste udskrive en stabelspor, så du ved, at undtagelsen blev kastet. Du kan gøre dette ved hjælp af | _+_ | metode.
  • Pas på med overforbrug af undtagelser. Når du har en hammer, ligner alt et søm. Når du først lærer om undtagelser, kan du føle dig forpligtet til at gøre alt til en undtagelse ... til det punkt, hvor størstedelen af ​​din applikations kontrolforløb kommer til håndtering af undtagelser. Husk, at undtagelser er beregnet til 'usædvanlige' begivenheder!

Nu skal du være komfortabel nok med undtagelser til at forstå, hvad de er, hvorfor de bruges, og hvordan du kan indarbejde dem i din egen kode. Hvis du ikke helt forstår konceptet, er det okay! Det tog mig et stykke tid, før det 'klikkede' i mit hoved, så du har ikke lyst til at skynde dig. Tag dig god tid.

Har du spørgsmål? Kender du andre undtagelsesrelaterede tips, som jeg savnede? Del dem i kommentarerne herunder!

Del Del Tweet E -mail Sådan opretter du et dataflowdiagram for at visualisere data fra ethvert projekt

Dataflowdiagrammer (DFD) for enhver proces hjælper dig med at forstå, hvordan data flyder fra kilden til destinationen. Sådan opretter du det!

Læs Næste
Relaterede emner
  • Programmering
  • Java
Om forfatteren Joel lee(1524 artikler udgivet)

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

hvordan man gendanner slettede billeder fra Android
Mere fra Joel Lee

Abonner på vores nyhedsbrev

Tilmeld dig vores nyhedsbrev for at få tekniske tips, anmeldelser, gratis e -bøger og eksklusive tilbud!

Klik her for at abonnere