1 Poikkeustenkäsittely Mitä poikkeustenkäsittely tarkoittaa? Poikkeuksen käsitteleminen Poikkeusluokkien hierarkia Poikkeuksen heittäminen 1 Mitä poikkeustenkäsittely tarkoittaa? Poikkeus (Exception) on tarkoittaa sitä, että ohjelmassa tapahtuu jotain epänormaalia esim. ohjelma kaatuu kesken suorituksen. Ohjelman kaatuminen voi johtua mm. siitä, että käyttäjä syöttää numeron sijaan kirjaimia. Jotta ohjelma toimisi poikkeuksesta huolimatta, ohjelmaan voidaan koodata poikkeustenkäsittely. Osa poikkeuksista on sellaisia, jotka on pakko käsitellä (esim. varautuminen tiedostoja käsiteltäessä tiedoston puuttumiseen) tai vapaaehtoisia (esim. varautuminen virheelliseen syötteeseen). 2
2 Poikkeusten käsitteleminen Poikkeukseen varaudutaan siten, että poikkeuksen mahdollisesti aiheuttava koodi laitetaan try-catch lohkon sisään. // koodia, missä poikkeus voi tapahtua catch (Exception e) { // mitä tehdään kun poikkeus tapahtuu finally { // suoritetaan aina Jos koodissa tapahtuu poikkeus, try-lohkon suoritus loppuu kesken ja siirrytään catch-lohkoon. Jos koodissa ei tapahdu poikkeusta, try-lohko suoritetaan loppuun ja catch-lohkoa ei suoriteta ollenkaan. Lisäksi voidaan laittaa finally-lohko, mikä suoritetaan aina lopuksi. 3 Try-Catch-esimerkki public static void main(string[] args) { Tili tili = new Tili(); double maara; Tee ohjelma, jolla tilille tehdään pano. Scanner input = new Scanner(System.in); System.out.print("Anna tilille panon määrä: "); jos käyttäjä antaa muuta kuin luvun, koodin suoritus siirtyy catch-lohkoon maara = input.nextdouble(); tili.pano(maara); System.out.println("Pano onnistui"); catch (Exception e) { System.out.println("Pano epäonnistui, määrä ei ole luku"); 4
3 Poikkeusluokkien hierarkia Seuraavalla sivuilla on esittely poikkeusluokkien periytymishierarkia. Hierarkiassa ylimpänä on Trowable-yliluokka, josta periytyy Error- ja Exception-nimiset aliluokat. Luokkakaaviossa periytymisyhteys kuvataan luokkien välisellä yhteysviivalla, jonka yliluokan päässä on kolmiosymboli. 5 Poikkeusluokkia Vakavat peruttamattomat virheet, joihin ohjelmoija ei aina voi vaikuttaa (esim. muistin loppuminen ohjelman suorituksen aikana). Trowable Ohjelmointivirheet ja ohjelman suoritusaikaiset virheet (esim. viitataan taulukon rajojen ulkopuolelle). Error Exception IOException Aliluokkia, jotka kertovat poikkeuksen syyn tarkemmin Tilanteet, joita ohjelmoija ei välttämättä tiedä etukäteen, mutta ne on huomioitava ohjelmakoodissa. (esim. yritys lukea tiedoston lopun yli, yritys hakea verkosta olematonta resurssia). RuntimeException jatkuu 6
4 jatkuu ed. sivulta RuntimeException IndexOutOfBoundsException IllegalArgumentException NullPointerException ArithmeticException NumberFormatException ArrayIndexOutOfBounds -Exception Yritetään käyttää oliota, mitä ei ole Merkkijonoa ei voida muuntaa luvuksi 7 Try-esimerkki (monta catch:a) public static void main(string[] args) { Tili tili = null; double maara; Tee ohjelma, joka tekee tilille panon Scanner input = new Scanner(System.in); System.out.print("Anna tilille panon määrä: "); maara = input.nextdouble(); tili.pano(maara); Kutsutaan metodia oliolle, jota ei ole System.out.println("Pano onnistui"); catch (NullPointerException e) { System.out.println("Tiliä ei ole"); catch (Exception e) { System.out.println("Pano epäonnistui, määrä ei ole luku"); /* Kun catch-osia on monta, laitetaan periytymishierarkiassa alempi poikkeustyyppi ennen ylempää tyyppiä(tässä NullPointerException ennen 8 Exception:a) */
5 Poikkeuksen heittäminen Try-catch-lohkossa voidaan poikkeus myös heittää (throw) metodien kutsuketjussa ylöspäin. Tällöin toinen metodi käsittelee poikkeuksen. Poikkeuksen heittävä metodi esitellään tyyliin: näkyvyys tyyppi metodinnimi(parametrit..) throws poikkeustyyppi1,, poikkeustyyppi_n Poikkeuksen heittävää metodia on aina kutsuttava try-lohkossa, jotta ollaan valmiita ottamaan kiinni mahdollinen poikkeus. 9 Throw-esimerkki Esimerkissä metodi pyydakokonaisluku() heittää tarvittaessa ajoaikaisen poikkeuksen. private static int pyydakokonaisluku() throws NumberFormatEx ception { String syote; int luku; System.out.println("Anna kokonaisluku: "); syote = input.nextline(); luku = Integer.parseInt(syote); // voi heittää poikk. catch (NumberFormatException e) { throw e; // throw lopettaa myös metodin suorituksen return luku; Ohjelman main()-metodissa pitää tätä metodia kutsua aina trycatch-lohkossa (kts. seur. sivu). 10
6 Throw-esimerkki jatkuu public static Scanner input = new Scanner(System.in); public static void main(string[] args) { int ika; boolean oksyote = false; do { ika = pyydakokonaisluku();//metodi voi heit. poikk. oksyote = true; catch (NumberFormatException e) { System.out.println("Syötä kokonaisluku numeroina!"); while (oksyote!= true); //... ohjelma jatkuu System.out.println("Kiitos ohjelman käytöstä"); 11 printstacktrace() Exception-luokalla on mm. metodi printstacktrace(). Metodi tulostaa tiedon siitä, minkä metodien kutsuketjun seurauksena poikkeus tapahtui. // koodia, missä poikkeus voi tapahtua catch (Exception e) { e.printstacktrace(); finally { // suoritetaan aina 12