220 likes | 307 Views
Opintojakso TT00AA11 Ohjelmoinnin jatko (Java): 3 op. Poikkeukset ja tietovirrat: Virhetilanteiden ja syötevirtojen käsittely. Poikkeukset. Poikkeuksella tarkoitetaan yllättävää ajonaikaista tilannetta, joka estää ohjelman normaalin suorituksen . Esimerkkejä: nollalla jako
E N D
Opintojakso TT00AA11 Ohjelmoinnin jatko (Java): 3 op Poikkeukset ja tietovirrat: Virhetilanteiden ja syötevirtojen käsittely
Poikkeukset • Poikkeuksella tarkoitetaan yllättävää ajonaikaista tilannetta, joka estää ohjelman normaalin suorituksen. • Esimerkkejä: • nollalla jako • avattavaa tiedostoa ei löydy • saadaan syötteenä tekstiä, vaikka yritetään lukea kokonaisluku • viitataan taulukon alkioon, jonka indeksi on indeksirajojen ulkopuolella. Vesa Ollikainen & Outi Grotenfelt
Poikkeusten ryhmät • Javassa poikkeus on olio, joka luodaan ongelmatilanteen syntyessä. • Poikkeusten ryhmät • tarkistettavat poikkeukset • syntyvät tilanteissa, joihin hyvin kirjoitetun ohjelman on varauduttava (esim. virheellinen tiedostonimi) • ohjelmoijan on määritettävä poikkeuksen käsittely (tarkistetaan käännösvaiheessa) • virheet • järjestelmän väärä toiminta (esim. viallinen laite) • poikkeukseen ei tarvitse/ei voi varautua • ajonaikaiset poikkeukset • seurausta ohjelmointivirheistä • pyritään välttämään, ei tarvitse varautua • Virheitä ja ajonaikaisia poikkeuksia kutsutaan tarkistamattomiksi poikkeuksiksi. Vesa Ollikainen & Outi Grotenfelt
Esimerkki: nollalla jako • Tarkastellaan esimerkkinä ohjelmaa, joka selvittää, montako makeista jokaiselle riittää, kun makeispussin sisältö jaetaan tasan. • Esimerkeissä käytetään esimerkkinä poikkeuksesta ajonaikaista virhettä: nollalla jakoa. • Nollalla jakoa käytetään esimerkissä yksinkertaisuuden vuoksi. • Kyseiseen virhetilanteeseen olisi luontevampaa varautua ”perinteisin” keinoin. • Toistorakenne syötteen kysymiseksi uudelleen, jos jakajana on nolla. Vesa Ollikainen & Outi Grotenfelt
Esimerkki: nollalla jako import java.util.*; public class Jakaja { public static Scanner input = new Scanner(System.in); public static void main(String[] args) { int lkm, henkilot, annos; System.out.print("Montako makeista pussissa on: "); lkm = input.nextInt(); System.out.print("Monelleko henkilölle ne jaetaan: "); henkilot = input.nextInt(); annos = lkm / henkilot; System.out.println("Jokainen saa "+annos+" makeista."); } } • Esimerkissä makeisten määrä jaetaan ihmisten määrällä (kokonaisjako). • Käyttäjä voi syöttää ihmisten määräksi nollan. • Nolla aiheuttaa ArithmeticException-poikkeuksen. run: Montako makeista pussissa on: 10 Monelleko henkilölle ne jaetaan: 0 Exception in thread "main" java.lang.ArithmeticException: / byzero at ekaesim.Jakaja.main(Jakaja.java:13) Java Result: 1 BUILD SUCCESSFUL (totaltime: 1 second) Vesa Ollikainen & Outi Grotenfelt
import java.util.*; public class Jakaja { public static Scanner input = new Scanner(System.in); public static void main(String[] args) { int lkm, henkilot, annos; System.out.print("Montako makeista pussissa on: "); lkm = input.nextInt(); System.out.print("Monelleko henkilölle ne jaetaan: "); henkilot = input.nextInt(); try { annos = lkm / henkilot; System.out.println("Jokainen saa "+annos+" makeista."); } catch (ArithmeticException e) { System.out.println(”Virhe: nollajako!”); } } } Poikkeukseen varautuminen • Riskialtis koodi kirjoitetaan try-lohkoon. • Jos try-lohkon suoritus aiheuttaa poikkeuksen, hypätään catch-lohkoon, jossa poikkeus käsitellään. run: Montako makeista pussissa on: 10 Monelleko henkilölle ne jaetaan: 0 Virhe: nollajako! BUILD SUCCESSFUL (totaltime: 1 second) Vesa Ollikainen & Outi Grotenfelt
try/catch-rakenne try { // riskialtis koodi } catch (poikkeustyyppi_1 e) { // poikkeustyypin 1 käsittely } catch (poikkeustyyppi_2 e) { // poikkeustyypin 2 käsittely } … catch (Exception e) { // kaikkien (muiden) poikkeustyyppien käsittely } finally { // lopetustoimenpiteet } Vesa Ollikainen & Outi Grotenfelt
try/catch-rakenne • Poikkeuksenkäsittelijöitä (catch-lohkoja) voi olla useita • Suoritettava käsittelijä määräytyy poikkeuksen tyypin mukaan • Jos poikkeustyypiksi määritellään Exception, suoritetaan se kaikille poikkeuksille. • Jos mukana on poikkeuskohtaisia käsittelijöitä, on yleinen käsittelijä kirjoitettava viimeiseen catch-lohkoon. • Finally-lohkon toimenpiteet suoritetaan joka tapauksessa • try-lohkon suorituksen jälkeen tai • poikkeuksenkäsittelijän suorituksen jälkeen. Vesa Ollikainen & Outi Grotenfelt
Poikkeuksen siirto import java.util.*; public class Jakaja2 { public static void jaaKarkit() throws ArithmeticException{ int lkm, henkilot, annos; Scanner input = new Scanner(System.in); System.out.print("Montako makeista pussissa on: "); lkm = input.nextInt(); System.out.print("Monelleko henkilölle ne jaetaan: "); henkilot = input.nextInt(); annos = lkm / henkilot; System.out.println("Jokainen saa "+annos+" makeista."); } } • Poikkeus voidaan siirtää kutsuvan ohjelmanosan tai virtuaalikoneen käsiteltäväksi. • throws-lauseella luetellaan siirrettävät poikkeukset. Vesa Ollikainen & Outi Grotenfelt
Poikkeuksen käsittely kutsuvassa luokassa • Siirretty poikkeus on käsiteltävä kutsuvassa lohkossa tai siirrettävä eteenpäin virtuaalikoneelle. Vesa Ollikainen & Outi Grotenfelt
Oman poikkeusluokan luonti • Oma poikkeusluokka määritetään Exception-luokan aliluokaksi. • Jos poikkeusluokasta tehtäisiin RunTimeException-luokan aliluokka, ei käännösaikana vaadittaisi poikkeuksen sieppaamista. • Varattu ohjelmointivirheille (APIn väärän käytön varalta) • Poikkeuksen käsittelytoimenpiteet on kirjoitettu poikkeusluokan konstruktoriin. • Tässä vasta luodaan poikkeusoliota, mutta ei tulosteta mitään. • Poikkeusluokan konstruktori kutsuu yliluokan (Exception) konstruktoria, joka saa parametrinaan virheilmoituksen. Vesa Ollikainen & Outi Grotenfelt
Oman poikkeusluokan käyttö • Poikkeus luodaan throw-lauseella. • Tarvittava poikkeusolio voidaan luoda samalla (new). Vesa Ollikainen & Outi Grotenfelt
Oman poikkeusluokan käyttö • Testiluokassa on käsiteltävä heitetty poikkeus tai siirrettävä se edelleen virtuaalikoneelle. • Tässä kutsutaan poikkeusoliolle Exception-luokasta perittyä metodia printStackTrace. • Metodi kutsuu poikkeusolion toString-metodia (jolla on nyt tieto poikkeukseen liitettävästä merkkijonosta). • Tämän jälkeen printStackTrace-metodi kutsuu metodia, joka tulostaa odottavien metodien pinon Vesa Ollikainen & Outi Grotenfelt
Tietovirrat • Poikkeusten käsittely (erityisesti IOException) on keskeistä tietovirtojen käytössä. • Tietovirta on yksisuurtainen syöte- tai tulostevirta • syötevirrasta luetaan • tulostevirtaan tulostetaan • Pakkaus java.io sisältää valmiita luokkia tietovirtojen käsittelyyn. • Tietovirran käsittelyn vaiheet • tietovirta luodaan (jolloin tiedosto avataan) • tietoa luetaan yleensä toistorakenteen sisällä • tiedosto suljetaan • Virhetilanteiden synnyttämiin poikkeuksiin (esim. tiedosto puuttuu tai on tyhjä) on varauduttava. Vesa Ollikainen & Outi Grotenfelt
Merkkipohjaiset tietovirrat • FileReader-luokan avulla voidaan avata tiedosto. • BufferedReader-oliosta voidaan lukea syötettä rivi kerrallaan. FileReader-olio annetaan parametrina. • Rivin jäsentäminen voidaan tehdä String.split-metodin avulla • Seuraava esimerkki lukee henkilöiden UTF-8-koodattua verenpainedataa ja tulostaa sen konsolille muotoiltuna. Esimerkkitiedostoa: Vesa Ollikainen & Outi Grotenfelt
Esimerkki Vesa Ollikainen & Outi Grotenfetl
Tietovirtojen käsittelystä • Syötteen kirjoittamiseen on analogiset luokat • FileWriter • BufferedWriter • Syötteitä ja tulosteita voidaan käsitellä myös tavupohjaisesti. • FileInputStream / FileOutputStreamtiedostoje käsittelemiseksi • DataInputStream / DataOutputStream -luokat perustietotyyppien syöttämiseksi ja tulostamiseksi Vesa Ollikainen & Outi Grotenfelt
Oliovirrat • Oliovirtojen avulla voidaan lukea ja kirjoittaa ohjelmassa olevien olioiden tila pysyvää tallennusta varten. • Tallennettavien olioiden on toteutettava Serializable-rajapinta. • Lukeminen ja kirjoittaminen tapahtuu ObjectInputStream / ObjectOutputStream -luokkien avulla. Vesa Ollikainen & Outi Grotenfelt
Esimerkki: Luokka, jonka olioita tallennetaan Vesa Ollikainen & Outi Grotenfelt
Esimerkki: Tallennus • ObjectOutputStream-luokanmetodi writeObject kirjoittaa olion tilan. Vesa Ollikainen & Outi Grotenfelt
Esimerkki: Luku • ObjectInputStream-luokan metodi readObject lukee olion tilan. Vesa Ollikainen & Outi Grotenfelt
THANK YOU! www.metropolia.fi/en/ www.facebook.com/MetropoliaAMK outi.grotenfelt@metropolia.fi