Kurt Nørmark ©
Department of Computer Science, Aalborg University, Denmark
September 2001
Abstract Previous lecture Next lecture Index References Contents | Vi har valgt at bruge betegnelsen 'undtagelseshåndtering' som overskrift til denne lektion. En anden, og måske mere ligefrem mulighed havde været 'fejlhåndtering'. Vi starter med at motivere området ved at se på forskellige problemstillinger der trænger sig på. Dernæst afklarer vi terminologi og begreber. Med dette ender vi med at tillægge forskellige betydninger til ordene 'fejl' og 'undtagelse'. Efter denne begrebs- og terminologiafklaring går vi over til at studere Java. Vi bruger naturligvis de begreber vi har lagt fast, men vi skal være opmærksomme på, at Java terminologien ofte kommer lidt tværs af vores. Vi slutter lektionen af med at studere fejlhåndtering i forlængelse af specifikation, kontrakter og ansvarsfordeling, som vi jo har set på i detaljer i en tidligere lektion |
Motivation og problemstillinger |
Normal- og fejltilfælde behandles under ét Slide Note Contents Index References Speak | I denne første afdeling af lektionen tager vi et antal forskellige problemstillinger op til behandling. Vi starter med at se på programmer, hvor normaltilfælde og fejltilfælde behandles samlet. Dette giver ofte uoverskuelige programmer |
|
Program: Et program uden fejlhåndtering som kopierer én fil over på en anden.
Vi har tidligere i kurset set på netop dette program.
Læg mærke til at programmet kan give anledning til en IOException.
|
|
Program: Et (pseudo)program med fejlhåndtering som kopierer én fil over på en anden.
Bemærk at programmet forsøger at holde al fejlhåndteringen inden for rammerne
af kopieringsprogrammet.
Derfor giver denne udgave af programmet ikke anledning til at main kan kaste et
exception.
Programmet forsøger side om side med kopieringsaspekterne (normaltilfældet) at
håndtere en række fejltilfælde.
Vi har farvelagt fejlaspekterne med rødt. De sorte dele af programmet
udgør de normale kopieringsdele af programmet.
Programmet tager udgangspunkt i ovenstående program,
men det er ikke gennemført i 100 procent Java.
|
|
Vi har tidligere - i anden sammenhæng - set på ansvarsfordeling mellem klient og forsyner (mellem kalder og den kaldte procedure). Her lader vi op til en anden form for ansvarsfordeling, nemlig mellem normaltilfælde og undtagelsestilfælde |
|
Fejl søges håndteret tæt på det sted hvor fejlene opstår Slide Note Contents Index References Speak | Det er i mange situationer ikke muligt eller hensigtsmæssigt at håndtere en fejl i umiddelbar nærhed af det sted, hvor fejlen opstod. Vi ser her nærmere på denne problematik. |
|
|
Unuanceret viden om fejlens natur Slide Note Contents Index References Speak | Vi ser her på den problemstilling der består i, at vi ikke har nok information om fejlens natur. Det er forudsætning for fejlhåndtering, at vi kender fejlens egenskaber i rimelig detalje |
|
|
|
Hvilken slags fejlhåndtering? Slide Note Contents Index References Speak | Her ser vi på hvad det egentlig vil sig at håndtere en fejl |
|
|
Terminologi og begreber |
Mange forskellige ord Slide Note Contents Index References Speak | Når man gennemser litteratur om emnet støder man på en del forskellige ord, som er relateret til fejlbehandling. Her opremser vi en række af disse. På næste side vil vi tillægge nogle af disse en klar og tydelig mening |
|
Table. En række ord på dansk og engelsk som benyttes når vi interesserer os for fejl |
|
|
Grundliggende begreber Slide Note Contents Index References Speak | Tiden er nu inde til at fastlægge betydningen af tre ord: 'fejl', 'defekt' og 'undtagelse'. Disse tre ord afspejler problemer i hhv. programmeringsprocessen, programbeskrivelsen og programudførelsen. Vi er inspireret af bogen 'Object-oriented Software Construction' af Bertrand Meyer |
The concept fejl: En fejl er en forkert beslutning i programudviklingsprocessen | En fejl er noget som sker når man programmerer. En fejl betegner en forkert beslutning i udviklingsarbejdet | |
The concept defekt: En defekt er en egenskab af et program som kan forårsage, at programmet afviger fra den påtænkte (specificerede) opførsel | En defekt er den afledte konsekvens, som en fejl har på kildeprogrammet. En defekt er således en (dårlig) egenskab ved et program | |
The concept undtagelse: En undtagelse er en hændelse i programudførelsen som kan forårsage afvigende eller fatal opførsel i forhold til intensionen (specifikationen) | En defekt kan føre til en undtagelse når programmet køres. En undtagelse er altså køretids manifestationen af en fejl og af en programdefekt. En undtagelse er udtryk for afvigende eller fatal opførsel af programmet i forhold til specifikationen af programmet |
|
Undtagelseshåndtering i Java |
Oversigt over undtagelseshåndtering i Java Slide Note Contents Index References Speak | Inden vi kaster os over de mange detaljer i Java's undtagelseshåndtering giver vi her en oversigt over de væsentligste forhold i Javas dækning af emnet |
|
Til de dynamiske aspekter henregnes det faktum, at exceptions er objekter i Java samt at exceptions propageres langs kæden af kaldte metoder. Til de statiske aspekter bidrager at exceptions erklæres som klasser, at metoder erklærer hvilke exceptions metoden kan afstedkomme samt at compileren kan checke aspekter af undtagelseshåndteringen. Alle disse forhold vil blive diskuteret i yderligere detalje senere i denne lektion |
Catch or specify princippet i Java Slide Note Contents Index References Speak | Inden vi går videre nævner vi et princip, som er karakteristisk for Java's omgang med exceptions. Vi vender tilbage til emnet senere i lektionen |
|
|
Program: Et program med compile fejl.
Hovedprogrammet kalder eksplosion uden hverken at håndtere fejlen, eller specificere den.
|
|
Program: Et program som håndterer et Problem.
Hovedprogrammet håndterer via en try-catch konstruktion fejlen.
|
|
Program: Et program som specificerer et Problem.
Programmet går ned under kørslen, fordi Problem ikke håndteres nogetsteds.
|
|
Klassificering af undtagelser i Java Slide Note Contents Index References Speak | Der er mange forskellige undtagelser, som kan opstå når vi bruger Java bibliotekerne. Endvidere kan vi definere vore egne undtagelser. Vi ser her på hvordan eksisterende og nye undtagelser klassificeres på det mest generelle niveau |
|
Figure. Toppen af exception klassehierarkiet i Java. De med fedt fremhævede klasser er centrale i hierarkiet. | ![]() |
Vi tænker her på det forfærdelige ord 'throwable' og på den misvisende kategori af undtagelser som kaldes RuntimeExceptions. Alle undtagelser er runtime exceptions! |
Exercise 10.1. Undtagelser i tallæsningsprogrammet | Én af de første øvelser vi lavede i kurset (lektion 2) gik ud på at indlæse et tal fra tastaturet ved at læse en række enkelte tegn.
Genfind jeres løsning på denne opgave, eller tag min løsning , som også
findes på filen talLaesning.java
|
|
Beskrivelse af exception klasser i Java (1) Slide Note Contents Index References Speak | Vi vil her karakterisere de generelle exception klasser i Java, som vi introducerede på forrige side |
At Error exceptions ikke er underlagt catch or specify princippet betyder at disse exceptions ikke skal specificeres i metoders throws clauses De sidstnævnte to eksempler på Errors forekommer ikke i 'normale' java programmer, idet de fanges under oversættelsen. Hvis man imidlertid tilgår objekter, som er lagret persistent på disken, eller hvis man via et klassenavn tilgår selv klassen med henblik på instantiering, kan disse fejl opstå |
|
Beskrivelse af exception klasser i Java (2) Slide Note Contents Index References Speak | Vi fortsætter her vores beskrivelse af de centrale exception klasser i Java |
Der er en pragmatisk årsag til at man vælger at afvige fra 'catch or specify' princippet for de mest hyppige undtagelser i Java. Det vil simpelthen være for stor en byrde at skulle fange (håndtere) eller erklære (specificere) alle sådanne fejl. Enhver metode ville være fuld af undtagelseshåndtering, og der ville være massevis af erklæringer af ikke håndterede exceptions på alle metoder. |
|
Exercise 10.2. Klassificering af undtagelser i CircularList | I klassen CircularList , som vi første gang mødte i lektionen om arrays og lister,
er der flere forhold som på en naturlig måde giver anledning til kastning af undtagelser
Tag evt. udgangspunkt i min løsning fra den tidligere lektion. |
Instantiering og 'kastning' af exceptions Slide Note Contents Index References Speak | Her vil vi se hvorledes man instantierer en exceptionklasse, samt ikke mindst hvordan den 'kastes' |
|
Syntax: Syntaks for 'kastning af en undtagelse'. Exception refererer til et objekt, som er en instans af en exception klasse (eller mere præcis, en instans af en klasse der arver fra Throwable). |
|
Program: Et eksempel på en throw kommando samt den underliggende Exception klasse.
|
|
Håndtering af exceptions i en metode Slide Note Contents Index References Speak | Når fejlen skal håndteres sker det i en metodes exception handler. Vi ser her på de sproglige mekanismer i Java, der tillader os at knyttet exception handlers til kommandoer i en metodes krop |
|
Syntax: Syntaks for try kommandoen i Java. Det giver mening at tænke på denne som en form for kontrolstruktur i sproget. En try konstruktion udgør scopet for fejlhåndtering. Kommandoblokken i try delen udføres (eller forsøges udført, som antydet af 'try syntaksen'). Hvis der herved opstår en undtagelse vil denne blive forsøgt håndteret af en catch længere fremme i konstruktionen. Den første catch som matcher det exception, som er opstået, binder undtagelsesobjektet til den formelle parameter (ligesom ved parameteroverførsel) hvorefter blokken efter catch udføres. Der udføres kun denne ene catch. Catches må ikke gentages, men det er tilladt at fange en specifik exception først for dernæst at fange en mere generel exception. |
|
At den formelle exception parameter er polymorf betyder, at den kan antage exceptions, som er instanser af vilkårlige subklasser af den angivne exception klasse |
Program: Et konkret eksempel på en try catch konstruktion.
De metoder, som kan forårsage kastning af et exception er refereret
andetsteds fra denne side.
|
|
|
Propagering af exceptions (1) Slide Note Contents Index References Speak | Et eksisterende exception objekt udbredes fra problemets kilde til det sted, hvor fejlen håndteres. Vi illustrerer her hvordan fejlen udbredes |
|
Figure. Illustration af fejludbredelse efter at der opstår et exception i metoden s. | ![]() |
|
Propagering af exceptions (2) Slide Note Contents Index References Speak | Her fortsætter vi diskussionen af exception propagering med en serie af billeder, der trin for trin illustrerer hvordan et kast af et exception kan forløbe når der indgår reparation af problemet i den sidste ende |
Image series: En trin for trin variant af billedet om fejludbredelse, herunder recovery. | En trin for trin variant af billedet om fejludbredelse, herunder recovery. |
Image no. 1. Efter at main har kaldt p, som har kaldt q, som har kaldt s opstår der en undtagelse i s. s håndterer ikke undtagelsen selv (men erklærer i sin signatur at den kaster en bestemt slags exception) | ![]() |
Image no. 2. Metoden s kaster en exception til sin kalder, som i dette tilfælde er r. Metoden r har nu chancen for at håndtere undtagelsen. Lad os antage, at det ikke sker. r kaster altså ligesom s en exception | ![]() |
Image no. 3. På fuldstændig samme måde opstår der en exception i metoden q. Lad os videre antage at heller ikke q håndterer undtagelsen. q kaster altså undtagelsen videre til p | ![]() |
Image no. 4. Der opstår nu en exception i p. Lad os antage at p håndterer undtagelsen på en sådan måde at programmet bringes på sporet igen. Vi er efterladt i positionen hvor p i en try blok har kaldt q | ![]() |
Image no. 5. På en eller anden måde løser en catch i try konstruktionen i p problemet | ![]() |
Image no. 6. p kalder nu en bedre version af q, her kaldet better_q. I programeksemplet herunder svarer dette til kaldet q(false) | ![]() |
Image no. 7. q kalder videre til r, igen i en 'bedre udgave' | ![]() |
Image no. 8. r kalder videre til s, på samme måde i en bedre udgave | ![]() |
Image no. 9. s undgår at komme i en undtagelsessituation. Og alle er lykkelige efter disse hårde strabadser | ![]() |
Program: Et Java program som opfører sig på samme måde som ovenstående billedserie.
I en gennemlæsning af programmet, se først på de blå dele (kaldskæden),
den røde del (det sted hvor der sker et exception), og de brune steder
(hvor undtagelsen bliver håndteret mv.)
|
|
Program: Output fra kørsel af ovenstående Java program.
|
|
Finally i Java's try blok (1) Slide Note Contents Index References Speak | I forlængelse af ovenstående behandling af try catch er det naturligt at introducere finally konstruktionen. En finally konstruktion bliver udført uanset hvilken vej man vælger ud af en try |
|
Syntax: Syntaks for try kommandoen i Java med en finally del. |
|
Finally i forhold til return, break og continue Slide Note Contents Index References Speak | Finally konstruktionen bør også studeres i forbindelse med de hop-agtige muligheder, som understøttes i Java, og som vi har mødt allerede tidligt i dette kursus. |
|
Program: Illustration af finally i forhold til return: Læsning af en fil indtil et bestemt tegn mødes.
I en try blok læser vi tegnene i filen in.
Hvis vi møder tegnet letter (en streng af længde én) returnerer vi umiddelbart true.
Hvis vi når hele vejen gennem løkken returnerer vi false.
Pointen i dette eksempel er, at finally blokken udføres når return er på vej ud
af metoden lookForLetter med enten true eller false.
Læg iøvrigt mærke til, at vi i dette eksempel har en try blok uden catch clauses,
men med en finally clause. Opstår der en IOException forplantes den
til main.
|
|
Program: Illustration af finally i forhold til break.
I en while løkke fra i løbende fra 0 til 9 bryder vi løkken når i bliver 5.
I hver udførelse af try-finally aktiveres udskrivninger både i try og finally delen naturligvis.
Når i bliver 5 kaldes break, men vi kan ikke komme ud af try-finally uden også at udføre
finally den sidste gang (altså for i == 5).
|
|
Program: Output af ovenstående program.
Bemærk specielt det med rødt fremhævede som stammer fra finally konstruktionens udførelse
efter at løkken er brudt med break kommandoen
|
|
Program: Illustration af finally i forhold til continue.
Eksemplet minder om break eksemplet ovenfor. Variablen i løber igen
fra 0 til 9. Når i er lige afbrydes løkken med continue, hvilket bevirker
at vi umiddelbart går til den næste i værdi i gennemløbet. Men uanset om i
er lige eller ulige vil finally-delen blive udført.
|
|
Program: Output af ovenstående program.
Løkkegennemløb med en lige værdi af variablen i afbrydes midtvejs.
Men uanset om i er lige eller ulige afsluttes løkken i finally blokken.
De med rødt fremhævede liner stammer fra finally konstruktionen udført i de tilfælde,
hvor løkken er blevet 'fortsat' med kald af continue
|
|
Hvis vi anvender den grove måde at stoppe et program på, System.exit(0), forbigår vi alle finally konstruktioner. System.exit bør således undgås når andre midler er tilgængelige for programafslutning |
|
|
Erklæring af exceptions i metoder Slide Note Contents Index References Speak | Som et centralt element diskuterer vi her en udvidelse af den måde vi erklærer metoder, der videregiver ikke håndterede execeptions |
|
Syntax: Syntaks for en metode definition med throw erklæringer. Det nye element, i forhold til hvad vi tidligere har set, er den anden linie som erklærer at metoden kan kaste bestemte typer af exceptions |
|
Program: Et Java program med fokus på erklærede exceptions i metoder.
Vi har tidligere i lektionen set på det samme program, nemlig i forbindelse med propagering af exceptions.
Hvorfor skal main erklære, at der kastes en exception? Fordi p tilsyneladende kan give anledning til
en exception. Men hvorfor specificerer p at der kan forekomme en exception - p håndterer jo netop
en undtagelse i en try! Det er fordi at q(false) kaldet i catch delen kan afstedkomme en exception.
|
|
|
Exceptions: Fristelser og byrder Slide Note Contents Index References Speak | Exceptions er ikke altid en velsignelse for de programmører, som skal anvender klasser hvori metoderne kaster exceptions. Her ser vi på problemet |
|
For god ordens skyld skal det bemærkes, at ovenstående fristelser bør modstås i de Java programmer, vi skriver |
|
Undtagelseshåndtering i forlængelse af kontraktbegrebet |
Kontrakter og undtagelser Slide Note Contents Index References Speak | Vi har i en tidligere lektion studeret kontraktbegrebet. Vi vil her gøre historien om kontrakter færdig i den specialsituation hvor kontrakten brydes |
|
|
|
En operation kan lykkes eller fejle Slide Note Contents Index References Speak | Når vi arbejder med metoder som er specificeret med pre- og postbetingelser har vi et godt grundlag til at definere success og fiasko. Vi vil benytte ordene hhv. 'at operationen lykkes' og 'operationen fejler' |
The concept operation lykkes: En operation lykkes hvis den efterlader programmet i en tilstand der opfylder postbetingelsen og klassens invariant | Vi siger at en operation lykkes hvis den opfylder kontrakten, når operationen er kørt til ende. At opfylde kontrakten i denne situation betyder at postbetingelsen skal være sand, samt at klasseinvarianten i den klasse, hvor metoden befinder sig, skal være sand | |
The concept operation fejler: En operation siges at fejle hvis den ikke lykkes | Som en naturlig modsætning siger vi at operationen fejler hvis den ikke lykkes |
Hvis en prebetingelse af en metode m brydes (bliver falsk) fejler den metode, som har kaldt m |
|
Hvis en metode har en postbetingelse der ikke blot er 'true' betyder det, at under visse omstændigheder vil postbetingelsen kunne brydes. Dette forårsager en exception, som måske skal håndteres uden for metoden. Metoderne på den dynamiske kæde af kald får chancen for at håndtere undtagelsen inden programmet evt. stopper sin udførelse. |
Exceptionhandling i en Eiffel routine Slide Note Contents Index References Speak | Vi viser her en en illustration af en routine (metode) i Eiffel, som har både pre- og postbetingelser. Vi fokuserer på de forskellige muligheder for success (lykkes) og failure (fejle) |
Figure.
| ![]() |
|
Chapter 10: Undtagelseshåndtering
Course home Author home About producing this web Previous lecture (top) Next lecture (top) Previous lecture (bund) Next lecture (bund)
Generated: March 31, 2008, 12:09:11