Výjimky v Javě

Z MiS
(Rozdíly mezi verzemi)
Přejít na: navigace, hledání
m (Opravy kódu.)
m (Oprava kódu příkladu.)
Řádka 78: Řádka 78:
  
 
  String nazev = "vstup.txt";
 
  String nazev = "vstup.txt";
 +
int cislo = 0;
 
  Scanner sc = null;
 
  Scanner sc = null;
 
  '''try''' {
 
  '''try''' {
 
     sc = new Scanner(new File(nazev), "windows-1250");
 
     sc = new Scanner(new File(nazev), "windows-1250");
     while (sc.hasNextLine()) {
+
    sc.useDelimiter("\\s*,\\s*|\\s*\r\n"); ''// Nastaví jako oddělovač položek čárku či konec řádku, mezery a tabulátory kolem čárky ignoruje.''
         int sirka = sc.nextInt();
+
     while (sc.hasNext()) {
         int delka = sc.nextInt();
+
         cislo = sc.nextInt();
 +
         int sirka = polozka;
 +
        cislo = sc.nextInt();
 +
        int delka = polozka;
 
         String popis = sc.next();
 
         String popis = sc.next();
        sc.nextLine();
 
 
         System.out.println("Pozemek: "+popis+" má šířku: "+sirka+" m a délku: "+delka+" m.");
 
         System.out.println("Pozemek: "+popis+" má šířku: "+sirka+" m a délku: "+delka+" m.");
 
         System.out.println("Plocha pozemku je: "+(sirka*delka)+" m^2.");
 
         System.out.println("Plocha pozemku je: "+(sirka*delka)+" m^2.");
Řádka 92: Řádka 95:
 
  } '''catch''' (FileNotFoundException ex) { System.err.println("Nenalezen soubor: "+nazev+"!");
 
  } '''catch''' (FileNotFoundException ex) { System.err.println("Nenalezen soubor: "+nazev+"!");
 
  } '''catch''' (IOException ex) { System.err.println("Chyba čtení ze souboru "+nazev+": "+ex.getLocalizedMessage());
 
  } '''catch''' (IOException ex) { System.err.println("Chyba čtení ze souboru "+nazev+": "+ex.getLocalizedMessage());
  } '''catch''' (InputMismatchException ex) { System.err.println("Nesprávný formát dat v souboru "+nazev+": "+ex.getLocalizedMessage());
+
  } '''catch''' (InputMismatchException ex) { System.err.println("Nesprávný formát čísla v souboru "+nazev+"! Poslední správně načtené číslo je: "+cislo+"!");
 
  } '''finally''' {
 
  } '''finally''' {
 
     sc.close();
 
     sc.close();
Řádka 98: Řádka 101:
  
 
  ...
 
  ...
 +
 +
<div class="Poznamka">
 +
Čtení textových souborů pomocí třídy <code>Scanner</code> je vhodný pouze pro velmi jednoduché textové soubory!
 +
 +
Pokud chcete vážně pracovat s&nbsp;CSV soubory, použijte některou z&nbsp;dostupných knihoven! Například: Univocity CSV parser!
 +
</div>
  
  
Řádka 126: Řádka 135:
 
  public void zpracuj() {
 
  public void zpracuj() {
 
     '''try''' {
 
     '''try''' {
 
+
 
         ''... nějaký kód... ''
 
         ''... nějaký kód... ''
 
+
 
         nactiSoubor();
 
         nactiSoubor();
 
+
 
         ''... nějaký kód - pokud v&nbsp;metodě ''nactiSoubor()'' nastane chyba, tento kód se přeskočí... ''
 
         ''... nějaký kód - pokud v&nbsp;metodě ''nactiSoubor()'' nastane chyba, tento kód se přeskočí... ''
 
+
 
     } '''catch''' (IOException ex) { ''... jak reagovat na chybu...''  
 
     } '''catch''' (IOException ex) { ''... jak reagovat na chybu...''  
 
     }
 
     }

Verze z 14. 4. 2020, 14:54


Obsah

Co jsou výjimky?

Ještě jednou pro ujasnění:

  • Neřešíme teď situaci, kdy je aplikace špatně naprogramovaná!
  • Aplikace je správně napsaná, ale problém nastane v něčem, co programátor nemůže dopředu ovlivnit.
  • Například výpadek sítě při komunikaci přes síť. Takové chyby lze předvídat a můžeme do aplikace zabudovat vhodnou reakci na takovou chybu. Ale nelze zajistit, aby taková chyba nenastala.


Jak výjimky fungují?

  1. Označíme blok kódu, kde chyba může nastat:
    try { ... }
  2. Následně zapíšeme kód bez toho, abychom museli neustále testovat chyby
    • Kód tedy může tedy zůstat přehledný a stručný, bez spousty podmínek.
    • Pokud chyba nastane, zbytek bloku kódu se přeskočí a ihned se provede reakce na chybu (viz další krok).
  3. Poté popíšeme, jak zareagovat na jednotlivé typy chyb (jak zareagovat na výjimky):
    catch (TypVýjimky názevVýjimky) { ... jak zareagovat ... }
    • Počet typů chyb, na které reagujeme, není omezený.
  4. A nakonec můžeme (ale nemusíme) uvést kód, který se má provést bez ohledu na to, jestli nastala chyba:
    finally { ... Co se má stát vždy na konci bloku ... }


Šablona kódu ošetření výjimek

try { // Začni provádět kód, ve kterém může nastat chybový stav...

    ... zde následuje kód, pracující se souborem...

} catch (TypVýjimky1 ex) { 

    // Co se má stát, pokud nastane chyba TypVýjimky1...

} catch (TypVýjimky2 ex) { 

    // Co se má stát, pokud nastane chyba TypVýjimky2...

    // Takto můžeme popsat reakci na různé typy výjimek.

} finally {

    // Co se má stát každopádně po skončení bloku...
    // Provede se i tehdy, kdy nastane neočekávaná chyba.

    // Část finally není povinná, může se vynechat...

}


Příklad — práce se souborem

import java.util.Scanner;
import java.io.*;
import java.util.InputMismatchException;
...
String nazev = "vstup.txt";
int cislo = 0;
Scanner sc = null;
try {
    sc = new Scanner(new File(nazev), "windows-1250");
    sc.useDelimiter("\\s*,\\s*|\\s*\r\n"); // Nastaví jako oddělovač položek čárku či konec řádku, mezery a tabulátory kolem čárky ignoruje.
    while (sc.hasNext()) {
        cislo = sc.nextInt();
        int sirka = polozka;
        cislo = sc.nextInt();
        int delka = polozka;
        String popis = sc.next();
        System.out.println("Pozemek: "+popis+" má šířku: "+sirka+" m a délku: "+delka+" m.");
        System.out.println("Plocha pozemku je: "+(sirka*delka)+" m^2.");
        System.out.println("---------------");
    }
} catch (FileNotFoundException ex) { System.err.println("Nenalezen soubor: "+nazev+"!");
} catch (IOException ex) { System.err.println("Chyba čtení ze souboru "+nazev+": "+ex.getLocalizedMessage());
} catch (InputMismatchException ex) { System.err.println("Nesprávný formát čísla v souboru "+nazev+"! Poslední správně načtené číslo je: "+cislo+"!");
} finally {
    sc.close();
}
...

Čtení textových souborů pomocí třídy Scanner je vhodný pouze pro velmi jednoduché textové soubory!

Pokud chcete vážně pracovat s CSV soubory, použijte některou z dostupných knihoven! Například: Univocity CSV parser!


Delegování chyb   throws

Například
  • Píšeme knihovní funkci, která bude sloužit pro načítání XML souborů v různých aplikacích.
  • Přitom ale nevíme, jaká aplikace to bude:
    • některé aplikace mohou být textové,
    • jiné mohou mít grafické uživatelské rozhraní,
    • a některé aplikace mohou být třeba napsány v Greenfootu.
  • Každá aplikace tedy bude chtít zareagovat na chybu jinak:
    • v textovém režimu vypsáním hlášení pomocí System.err.println(),
    • v grafickém režimu pomocí vyskakovacího okna
    • a v Greenfootu třeba tak, že nějakému aktérovi nastavíme text s popisem hlášení.
  • Chybu tedy nechceme ošetřovat hned, protože ještě nevíme jak to nejlépe provést.
private void nactiSoubor() throws IOException {
    ... kód, kde může nastat chyba IOException, na kterou ale v tomto místě neumíme správně zareagovat...
    ... další kód, který se v případě chyby přeskočí...
}
public void zpracuj() {
    try {

        ... nějaký kód... 

        nactiSoubor();

        ... nějaký kód - pokud v metodě nactiSoubor() nastane chyba, tento kód se přeskočí... 

    } catch (IOException ex) { ... jak reagovat na chybu... 
    }
}


Vyhození vlastní výjimky   throw

if (castka > limit) {
    int rozdil = castka - limit;
    throw new MyException("Překročen limit o: "+rozdil+" Kč");
}


Související stránky


Zdroje

Osobní nástroje
Jmenné prostory
Varianty
Akce
Výuka
Navigace
Nástroje