Download Håndtering av avbrudd – unntak og feil JavaGently kap. 4.4

Survey
yes no Was this document useful for you?
   Thank you for your participation!

* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project

Document related concepts
no text concepts found
Transcript
Håndtering av avbrudd
– unntak og feil
JavaGently kap. 4.4
© Institutt for informatikk – Gerhard Skagestein
IN105-javaunntak-1
Sett slikt ! ?
1: class Testunntak {
2:
public static void main ( String [ ] args ) {
3:
new Testunntak ( args );
4:
}
5:
Testunntak ( String [] args ) {
6:
System.out.println ( args[0] );
7:
int m = 3, k = Integer.parseInt( args[1]);
8:
int n = 2/(m-k);
9:
}
10:}
...>java Testunntak
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 0
at Testunntak.<init><Testunntak.java:6>
at Testunntak.main<Testunntak.java:3>
...>java Testunntak tull 3
tull
Exception in thread "main" java.lang.ArithmeticException: / by zero
at Testunntak.<init><Testunntak.java:8>
at Testunntak.main<Testunntak.java:3>
© Institutt for informatikk – Gerhard Skagestein
IN105-javaunntak-2
Hvordan håndtere det unormale
o Det hender at et program kommer i en unormal situasjon,
eksempelvis
o Divisjon med 0
o Indeksering av en tabell eller tegnstreng utenfor "kanten"
o Konvertering til tall av en feilaktig tekststreng
o Forsøk på å følge en null-peker
o Det er et ønskemål at programmeringen av det unormale
ikke forkludrer programmeringen av det normale
o Programlogikken bør vise den normale kontrollflyten
o Unormale situasjoner bør tas hånd om av
spesialkonstruksjoner i programmeringsspråket
© Institutt for informatikk – Gerhard Skagestein
IN105-javaunntak-3
Håndtering av det unormale i Java
o Når Java (mer nøyaktig: JVM) kommer opp i en unormal situasjon,
genereres ("kastes") et avbrudds-objekt ("en varm potet")
o Dette objektet inneholder opplysninger om årsaken til avbruddet,
og om på hvilket sted i programmet det skjedde
o Avbrudd kan være enten
o Unntak ("Exception")
» Aritmetiske feil, indeksfeil, bruk av null-pekere, …
» Feil under inn-ut-operasjoner, tilknytning til filer …
o Error
» Grusomme systemfeil vi ikke kan gjøre noe særlig med
© Institutt for informatikk – Gerhard Skagestein
IN105-javaunntak-4
Håndtering av unntak
o Metoden som forårsaket unntaket kan
o enten selv ta hånd om avbrudds-objektet og prøve å rette opp
situasjonen
o eller avslutte utførelsen og "kaste" avbrudds-objektet opp til
kallende metode ("exception propagation")
o eller la være å gjøre noe som helst
o Hvis en metode som får "den varme poteten" unnlater å
gjøre noe, vil programmet terminere med en feilmelding
Vi diskuterer heretter bare unntak –
"errors" kan vi jo ikke gjøre noe med…
© Institutt for informatikk – Gerhard Skagestein
IN105-javaunntak-5
Hvordan fange opp avbrudd
o Ta imot dem / ‘fange’ dem:
try{
... farlig kode....
} catch ( Exception e) {
... gjør noe fornuftig fordi ‘feil har oppstått..
} //end try
o Ta imot dem, gjøre noe og så kaste dem videre oppover:
try{
... farlig kode....
} catch ( Exception e) {
... gjør noe fornuftig fordi ‘feil har oppstått..
throw e;
Alle unntak er objekter
av klassen Exception
} //end try
(eller subklasser av
denne)
© Institutt for informatikk – Gerhard
Skagestein
Stein Gjessing
IN105-javaunntak-6
Eksempel på ikke oppfanget feil
1: class Unntak0 {
2: public static void main(String[ ] args) {
3:
new Unntak0 ( ) ; }
4: Unntak0 ( ) {
5:
int dividend=7, divisor = 0; int kvotient;
6:
kvotient = dividend/divisor;
7:
System.out.println(kvotient);
8: }
9: }
>java Exception0
.... Java.lang.ArithmeticException: / by zero
at Unntak0.<init>(Unntak0.java: 6)
at Unntak0.main(Unntak0.java: 3)
© Institutt for informatikk – Gerhard Skagestein
IN105-javaunntak-7
Enda et eksempel på ikke oppfanget feil
class Unntak1 {
public static void main(String[ ] args) { new Unntak1 ( ) ; }
Unntak1 ( ) {
String s="Dette er en tekst med 29 tegn"; String s1;
s1 = s.substring(30,32); // string-indeks utenfor "enden"
System.out.println(s1);
}
}
>java Unntak1
...java.lang.StringIndexOutOfBoundsException: String index out of range: 32
at java.lang.String.substring(String.java:1486)
at Unntak1.<init>(Unntak1.java:5)
at Unntak1.main(Unntak1.java: 2)
© Institutt for informatikk – Gerhard Skagestein
IN105-javaunntak-8
Vi fanger unntaket
class Unntak1a {
public static void main(String[ ] args) { new Unntak1a ( ); }
Unntak1a ( ) {
String s="Dette er en tekst med 29 tegn"; String s1;
try {
s1 = s.substring(30,32); // string-indeks utenfor "enden"
} catch (StringIndexOutOfBoundsException e) {
System.out.println("Her er det noe galt med string-indeksen");
s1 = "*********";
} //end try
System.out.println(s1);
}
}
>java Unntak1a
Her er det noe galt med string-indeksen
*********
© Institutt for informatikk – Gerhard Skagestein
IN105-javaunntak-9
Vi fanger unntaket, men sender det videre
class Unntak1b {
public static void main(String[ ] args) { new Unntak1b ( ); }
Unntak1b ( ) {
String s="Dette er en tekst med 29 tegn",s1;
try {
s1 = s.substring(30,32); // string-indeks utenfor "enden"
} catch (StringIndexOutOfBoundsException e) {
System.out.println("Her er det noe galt med string-indeksen");
throw e; //kast unntaket videre
} //end try
System.out.println(s1);
}
} >java Unntak1b
Her er det noe galt med string-indeksen
Java.lang.StringIndexOutOfBoundsException: String index out of range: 32
at java.lang.String.substring(String.java:1486)
at Unntak1b.<init>(Unntak1b.java: 6)
at Unntak1b.main(Unntak1b.java: 2)
© Institutt for informatikk – Gerhard Skagestein
IN105-javaunntak-10
A
Skisse
unntaksbehandling
Skisse
avavunntaksbehandling
B
try {
A kaller B
}
catch (Unntaksklasse unt) {
< Unntaksbehandling.
Dette hoppes over
når intet unormalt
har hendt >
}
< her fortsetter vanligvis
programmet
både etter normal
utføring og etter
behandling av
eventuelle unntak >
B oppdager en feil:
throw new Unntaksklasse ( ) ;
Normal retur fra B til A
Unntaksklasse er en forhåndsdeklarert
subklasse av klassen Exception.
Dette kommer vi tilbake til.
JavaGently Figur 4.6 – side 115
© Institutt for informatikk – Gerhard
Skagestein
Stein Gjessing
IN105-javaunntak-11
Utskrift av detaljer om unntaket
class Unntak1c {
public static void main(String[ ] args) { new Unntak1c ( ); }
Unntak1c ( ) {
String s = "Dette er en tekst med 29 tegn", s1;
try {
s1 = s.substring(30,32); // string-indeks utenfor "enden"
} catch (StringIndexOutOfBoundsException e) {
System.out.println("Her er det noe galt med string-indeksen " +
e.getMessage( ));
s1 = "*********";
} //end try
System.out.println(s1);
}
}
>java Unntak1c
Her er det noe galt med string-indeksen String index out of range: 32
*********
© Institutt for informatikk – Gerhard Skagestein
IN105-javaunntak-12
Tilordninger i try-blokken utføres ikke alltid
class Unntak1c {
public static void main(String[ ] args) { new Unntak1c ( ); }
Unntak1c ( ) {
String s = "Dette er en tekst med 29 tegn", s1;
try {
s1 = s.substring(30,32); // string-indeks utenfor "enden"
} catch (StringIndexOutOfBoundsException e) {
System.out.println("Her er det noe galt med string-indeksen ");
// s1 = "*********";
} //end try
System.out.println(s1);
}
}
...> javac Unntak1c.java
Unntak1c.java:15: Variable s1 may not have been initialized.
System.out.println(s1);
^
© Institutt for informatikk – Gerhard Skagestein
IN105-javaunntak-13
Test på flere unntak
class Unntak2a {
public static void main(String[ ] args) { new Unntak2a ( ) ; }
Unntak2a ( ) {
int dividend=7, divisor = 0; int kvotient=0;
String s="Dette er en tekst med 29 tegn"; String s1="*********";
try {
s1 = s.substring(15,17); // OK string-indeks
kvotient = dividend/divisor; // divisjon med 0
} catch (StringIndexOutOfBoundsException e) {
System.out.println("Her er det noe galt med string-indeksen");
} catch (ArithmeticException e1) {
System.out.println("Divisjon med 0: " + e1.getMessage( ) );
} //end try
>java Unntaka
System.out.println(s1);
Divisjon med 0: / by zero
System.out.println(kvotient);
St
0
}
}
© Institutt for informatikk – Gerhard Skagestein
IN105-javaunntak-14
Try – fullstendig utgave
Try-setning
Try {
setninger // farlig kode
} catch (Unntaksklasse1 variabel1) {
setninger
} catch (Unntaksklasse2 variabel 2) {
setninger
} finally {
setninger // disse utføres alltid!
} // end try
Både catch-leddene
og finally-leddet kan
utelates!
© Institutt for informatikk – Gerhard Skagestein
IN105-javaunntak-15
Kontrollerte unntak
o For en lang rekke av de unntakene som kan kastes av Java API
(dvs. klassebiblioteket) gjelder at kompilatoren kontrollerer at
de blir tatt hånd om
o Eksempelvis gir følgende program kompileringsfeil:
import java.io.*;
class Unntak3 {
Dette programmet skal
public static void main(String[ ] args) { new Unntak3 lese
( ); }fra tastaturet –
Unntak3 ( ) {
mer om det senere…
BufferedReader stdin =
new BufferedReader(new InputStreamReader(System.in));
String message;
System.out.println("Enter a line of text:");
message = stdin.readLine();
System.out.println("You entered: \" " + message + "\"");
} > javac Unntak3
}
…\Unntak3.java.9: Exception java.io.IOException must be caught,
or it must be declared in the throw clause of this method.
message = stdin.readLine();
© Institutt for informatikk – Gerhard Skagestein
IN105-javaunntak-16
Løsning A – fang unntaket
import java.io.*;
class Unntak3a {
public static void main(String[ ] args) { new Unntak3a ( ); }
Unntak3a ( ) {
int number = 0;
BufferedReader stdin =
new BufferedReader(new InputStreamReader(System.in));
System.out.println("Skriv inn et heltall");
try {
number = Integer.parseInt (stdin.readLine( ));
} catch (IOException e) {
System.out.println(e.getMessage( ) + " Avslutter!");
System.exit(0); // Dette kallet terminerer programmet
} // end try
System.out.println(number);
}
}
© Institutt for informatikk – Gerhard Skagestein
IN105-javaunntak-17
Løsning B –
deklarer at metoden kan kaste unntaket
import java.io.*;
class Unntak3b {
public static void main(String[ ] args) { new Unntak3b ( ) ; }
Unntak3b ( ) throws IOException {
int number = 0;
BufferedReader stdin =
new BufferedReader(new InputStreamReader(System.in));
String message;
Hvorfor insisterer Java på
System.out.println("Skriv inn et heltall"); dette?
number = Integer.parseInt (stdin.readLine( ));Jo, fordi det at en metode
kan kaste et unntak er en
System.out.println(number);
like viktig opplysning for
}
omgivelsene som selve
}
signaturen (metodenavn,
parametre og returverdier)
© Institutt for informatikk – Gerhard Skagestein
IN105-javaunntak-18
Løsning - fang unntaket til slutt
import java.io.*;
class Unntak3c {
public static void main(String[ ] args) {
try {
new Unntak3c ( ) ;
} catch ( IOException e) {
System.out.println (" Det skjedde noe galt ved lesing.");
}
}
Unntak3c ( ) throws IOException {
int number = 0;
........
number = Integer.parseInt (stdin.readLine( ));
System.out.println(number);
}
}
© Institutt for informatikk – Gerhard Skagestein
IN105-javaunntak-19
RuntimeExceptions
o Kompilatoren krever ikke at alle unntak skal tas hånd om på
denne måten
o De såkalte RuntimeExceptions (som divisjon med 0, indeks
utenfor "kanten", forsøk på å følge en null-peker, forsøk på
å konvertere en feilaktig tekststreng til et tall) kan
forekomme så mange steder at dette vil være upraktisk – vi
må heller forsøke å unngå dem…
>java Unntak3c
Skriv inn et heltall
g67
java.lang.NumberFormatException: g67
at java.lang.Integer.parseInt(Compiled code)
at java.lang.Integer.parseInt(Integer.java:458)
at Unntak3c.<init>(Unntak3c.java:15)
at Unntak3c.main(Unntak3.java:4)
© Institutt for informatikk – Gerhard Skagestein
Eksempel på
RuntimeException ved
kjøring av programmet
på forrige lysark med
ukorrekte inndata
IN105-javaunntak-20
Vi slår to fluer i en smekk
import java.io.*;
class Unntak3d {
public static void main(String[ ] args) { new Unntak3d ( ) ; }
Unntak3d ( ) {
int number = 0;
BufferedReader stdin = new BufferedReader(new InputStreamReader(System.in));
boolean korrekt = false;
while (! korrekt) { // gå i løkke inntil brukeren har gitt korrekte inndata
System.out.println("Skriv inn et heltall");
try {
number = Integer.parseInt (stdin.readLine( ));
korrekt = true;
} catch (NumberFormatException exception) {
System.out.println ("Ukorrekte inndata - skriv inn en gang til...");
} catch (IOException exception) {
System.out.println(exception.getMessage( ) + " Avslutter!");
System.exit(0); // Dette kallet terminerer programmet
} // end try
} // end while
System.out.println(number);
}
}
© Institutt for informatikk – Gerhard Skagestein
IN105-javaunntak-21
Hva skjer når vi kjører Unntak3d ?
...>java Unntak3d
Skriv inn et heltall
g67
Ukorrekte inndata - skriv inn en gang til ...
jsg
Ukorrekte inndata - skriv inn en gang til ...
67
67
...>
© Institutt for informatikk – Gerhard Skagestein
IN105-javaunntak-22
Lag ditt eget unntak!
class Mittunntak extends Exception {
public Mittunntak ( ) { }
public Mittunntak (String s ) { }
// end konstruktører
} // end class Mittunntak
….
…..
throw new Mittunntak("feilmelding");
© Institutt for informatikk – Gerhard Skagestein
Den nye klassen
Mittunntak bygger på
(extends) en Java APIklasse med navn
Exception. Detaljene i
dette skal vi komme
tilbake til
IN105-javaunntak-23