150 likes | 239 Views
Poikkeukset ja niiden paikallistaminen *. Jukka Juslin * Liittyy oppikirjan lukuun 11. Poikkeukset. Java-ohjelman suoritus voi keskeytyä poikkeustilanteeseen (engl. exception) Poikkeustilanteita on monentyyppisiä – perustyyppi kaikille poikkeuksille on Exception. Poikkeusten tarkoitus.
E N D
Poikkeukset ja niiden paikallistaminen * Jukka Juslin * Liittyy oppikirjan lukuun 11
Poikkeukset • Java-ohjelman suoritus voi keskeytyä poikkeustilanteeseen (engl. exception) • Poikkeustilanteita on monentyyppisiä – perustyyppi kaikille poikkeuksille on Exception
Poikkeusten tarkoitus • Java-ohjelman aiheuttaman poikkeuksen idea on hallitusti käsitellä ongelmatilanne • Jos poikkeus ns. otetaan kiinni ja käsitellään voidaan suoritusta jatkaa normaalisti • Tarkastellaan seuraavaa esimerkkiä
minkälainen ongelma tähän voi sisältyä? Poikkeusesimerkki package viikko12; import java.util.Scanner; public class Hinta { public void aja() { Scanner scan = new Scanner(System.in); System.out.println(”Anna ALV 0 hinta (esim. 12€):”); double hinta = scan.nextDouble(); System.out.println(”Hinta ALV 22%: ” + (1.22*hinta)); } public static void main(String[] args) { Hinta hinta = new Hinta(); hinta.aja(); } }
Edellinen ohjelma ”livenä” Ohjelman kaatuminen johtuu € merkistä, jota numeronlukija ei ymmärrä. Ohjelma kaatuu poikkeukseen rivillä 9 – tämä on itseasiassa hyperlinkki Eclipsessä, josta pääset oikealle riville.
Ohjelman korjaaminen – poikkeuksen käsittely • Edellinen ohjelma voidaan korjata lisäämällä poikkeuksenkäsittely • Poikkeuskäsittely tehdään yleensä aina lisäämällä try { } lohko, jossa mahdollisesti tapahtuva poikkeus otetaan kiinni catch-lohkossa • Seuraavalla kalvolla näet aikaisemman ohjelman korjattuna
package viikko12; import java.util.Scanner; public class Hinta { public void aja() { Scanner scan = new Scanner(System.in); System.out.println(”Anna ALV 0 hinta (esim. 12€):”); try { double hinta = scan.nextDouble(); System.out.println(”Hinta ALV 22%: ” + (1.22*hinta)); } catch(InputMismatchException ex) { System.out.println(”Syötit virheellisen luvun.”); } } public static void main(String[] args) { Hinta hinta = new Hinta(); hinta.aja(); } }
Lisäongelmia edelliseen esimerkkiin (1 / 2) • Joskus on mahdollista, että ohjelma jää ikisilmukkaan kun scanneriin jäänyt ylimääräinen enter jää lukematta • Olisi syytä aina numeroita luettaessa lukea ylimääräisellä scan.nextLine()-komennolla turha enter pois puskurista
Lisäongelmia edelliseen esimerkkiin (2 / 2) • Jotkin toiminnot on usein tehtävä siitä huolimatta onnistuiko syötteen lukeminen vai ei • Näinollen scan.nextLine()-komennon voisi sijoittaa finally-lauseeseen • Lisäksi voi miettiä miten tulee toimia, jos halutaan että ohjelma kysyy oikeaa syötettä niin kauan kunnes se annetaan?
Luentoharjoitus • Tee ohjelma PalkkaOhjelma.java, joka kysyy palkkoja. Jos palkka saadaan tekstimuodossa ohjelma kysyy uutta palkkaa niin kauan kunnes palkka saadaan oikeassa muodossaan. Palkat ovat desimaalukuja, eli siis double-tyyppiä.
Pakollinen virheentarkistus vs. ei pakollinen • Jossain tilanteissa on pakollista tehdä virheenkäsittely, esimerkiksi avattaessa tiedostoa Java-ohjelmasta käsin Scanner-luokkaa apunakäyttäen • Toisissa tilanteissa taas Scanner ei vaadi virheentarkistusta, kuten on näppäimistöltä luettavan syötteen tapauksessa – tämä on todennäköisesti tehty sen vuoksi että olisi helpompi kirjoittaa koodi, joka lukee näppäimistöltä
package viikko12; import java.util.Scanner; public class PakollisestiKasiteltavaPoikkeus { public void aja() { Scanner scan = new Scanner(new File(”lokitiedosto.txt”); scan.println(”testikirjoitus”); scan.close(); } public static void main(String[] args) { PakollisestiKasiteltavaPoikkeus poikkeus = new PakollisestiKasiteltavaPoikkeus(); poikkeus.aja(); } }
Poikkeuksien eteenpäin heitteleminen 1 / 2 • Poikkeuksia voidaan heittää käsiteltäväksi eteenpäin metodista throws-avainsanalla • Esimerkiksi: publicvoidtarkistaDokumenttiluokka(String luokka) throwsVaaraDokumenttiLuokka { if (!luokka.equals("V") && !luokka.equals("L") && !luokka.equals("S")) { throw new VaaraDokumenttiLuokka(); } }
Poikkeuksien eteenpäin heitteleminen 2 / 2 • Poikkeus päätyy lopulta komentorivipohjaisessa sovelluksessa main-metodiin, jos sitä ei aikaisemmin käsitellä • Jos poikkeusta ei käsitellä saadaan Eclipseen ns. stack-trace, jossa näkyy metodikutsujen ketju (pino) joissa viimeisenä tasona on kyseisen sovelluksen main-metodi • Stacktraceen voi tulla myös Javan sisäisen toteutuksen luokkia, jotka eivät ole ohjelmoijan itse tekemiä • Stractracen ilmoittamaan kohtaan päästään klikkaamalla kyseistä kohtaa
Omien poikkeusluokkien tekeminen • On mahdollista tehdä omia poikkeusluokkia, kun niiden alussa ilmoitetaan extendsException • Kyseinen vaatii kuitenkin periytymisen käyttämistä ja periytymistä ei tällä kurssilla juuri käsitellä • Kaikkien poikkeuksien kantaluokka on siis Exception, ja kuten ehkä aikaisemmasta huomattiin sillä saadaan pyydystettyä mikä tahansa poikkeustilanne