210 likes | 305 Views
Po čítače a programování 1. Obsah přednášky. Výjimky - základní typy výjimek Způsoby zpracování výjimek. Výjimky. Mechanismus výjimek v Javě umožňuje psát “bezpe čné programy ” , které dokáží reagovat na chybové stavy vzniklé za běhu programu.
E N D
Obsah přednášky • Výjimky - základní typy výjimek • Způsoby zpracování výjimek
Výjimky Mechanismus výjimek v Javě umožňuje psát “bezpečné programy”, které dokáží reagovat na chybové stavy vzniklé za běhu programu. Výjimka (exception) – událost popř. vyjímečný stav, o kterém si přejeme, aby v našem programu nenastal (např. dělění nulou, chybně zadané vstupy). Ve většině případů se jedná o kritický stav který má bez ošetření za následek předčasné ukončení programu
Druhy výjimek • Výjimky třídy Error – závažné chyby, které se mohou vyskytnout pouze v JVM, v našem programu na ně nereagujeme protože je stejně neumíme opravit (např. nedostatek paměti – výjimka OutOfMemoryError) • Výjimky třídy RuntimeException (asynchronní výjimky) – mohou se v běžícím programu vyskytnout kdekoliv, tento typ výjimek vyvolává JVM ( např. dělení nulou) – překladač nás nenutí na ně reagovat, ale můžeme, považujeme-li to za užitečné • Výjimky třídy Exception (synchronní výjimky) - nemohou se vyskytnout kdekoliv ale pouze v souvislosti s voláním některých metod u kterých je zvýšená pravděpodobnost že se při jejich použití může vyskytnout chyba (obvykle vstupy a výstupy) – tento typ výjimek musíme zpracovat, jinak nelze program přeložit
Způsob ošetření výjimek Programátor může na výjimku reagovat jedním ze tří způsobů : • Výjimku neumí (nebo nechce) ošetřovat – informaci o jejím výskytu předá nadřazené metodě • Výjimku zachytí a kompletně ošetří v metodě ve které se vyskytla • Výjimku částečně nebo kompletně ošetří v metodě a zároveň pošle informaci o jejím výskytu do nadřazené metody
Předání výjimky výše Používá se v případě, že se metoda “zříká odpovědnosti“ za zpracování výjimky nebo v případě že chceme informovat volající metodu že došlo k chybě Deklarace: v hlavičce metody pomocí klíčového slova throws Př. public static int ctiInt() throws NumberFormat{ …… } Pokud dojde během provádění metody ctiInt() k výjimce je metoda ukončena a výjimka předána výše do volající metody - ve většině případů do metody main, která ji musí ošetřit nebo předat do JVM
import java.io.*; public class Vyjimka { public static int ctiInt() throws IOException { byte[] pole = new byte[20]; String nacteno; int i; System.in.read(pole); nacteno = new String(pole).trim(); i = Integer.valueOf(nacteno).intValue(); return i; } public static void main(String[] args)throws IOException { System.out.print("Zadej pocet cihel: "); System.out.println("Cihel je: " + i); } }
Ošetření výjimky K ošetření výjimky se používá konstrukce try-catch Blok try ( tzv chráněný úsek) obsahuje kód ve kterém se může vyskytnout výjimka, blok catch říká na jakou výjimku (a jakým způsobem) se bude reagovat Př. Kvadratická rovnice – ošetření vstupů import vstup.*; public class Kvadrat{ public static void main(String [] args) { double a=0,b=0,c=0; double d,re,im; int koef=0; boolean rd;
do { try { switch (koef) { case 0: System.out.print("Zadej a: "); a=VstupData.ctiInt(); koef++ ; case 1: System.out.print("Zadej b: "); b=VstupData.ctiInt(); koef++ ; case 2: System.out.print("Zadej c: "); c=VstupData.ctiInt(); } rd=true; } catch ( NumberFormatException e) { rd=false; System.out.println("Chybne zadane koeficienty !!! Zadej znovu "); } } while (!rd); System.out.println("a : "+a+"\t b : "+b+"\t c : "+c ); if ((a==0) && (b==0)) {
if (c!=0) System.out.println("Rovnice nema reseni."); else System.out.println("Rovnice ma nekonecne mnoho reseni."); } else { if ((a==0) && (c!=0)) System.out.println("Rovnice je linearni. c=" + (-c/b) ); else { d=Math.pow(b,2.)-4*a*c; if (d>=0) { System.out.println("x1="+ (-b+ Math.sqrt(d))/(2*a)); System.out.println("x2="+ (-b+ Math.sqrt(d))/(2*a)); } else { System.out.println("x1="+ (-b/(2*a)) + " + j" + Math.sqrt(Math.abs(d))/(2*a)); System.out.println("x2="+ (-b/(2*a)) + " + j" + Math.sqrt(Math.abs(d))/(2*a)); } } } } }
Ošetření výjimky a předání výše Používá se v případech kdy chceme informovat volající metodu že došlo k chybě a nechceme vymýšlet speciální návratové hodnoty
import java.io.*; public class Vyjimka { public static int ctiInt() throws NumberFormatException { byte[] pole = new byte[20]; String nacteno; int i; try { System.in.read(pole); nacteno = new String(pole).trim(); i = Integer.valueOf(nacteno).intValue(); return i; } catch (IOException e) { System.out.println("Chyba pri cteni"); return 0; } catch (NumberFormatException e) { // System.out.println("Chyba pri cteni"); throw e; // vyhozeni vyjimky } }
public static void main(String[] args) { boolean opak=false; do { try { System.out.print("Zadej pocet cihel: "); int i = ctiInt(); System.out.println("Cihel je: " + i); opak=false; } catch (NumberFormatException e) { System.out.println("Chybne zadany vstup, zadejte znovu !!! "); opak=true; } } while(opak); } }
Minimální doporučená reakce na výjimku Výjimku je možné “chytit” a nereagovat na ni.V tomtopřípadě bude blok catchprázdný. Tento způsob však není vhodný a neměl by se používat !!!!! Minimálně by měl blok catch obsahovat následující volání metody: catch (Jmeno_Vyjimky e ) { e.printStackTrace(); } Která vypíše informace o tom kde chyba nastala a co bulo příčinou chyby. (tj. totéž co se vypíše v případě když výjimku vyhodíme do JVM - např. java.lang.NumberFormatException: For input string: "hodne" at java.lang.NumberFormatException.forInputString(Unknown Source) at java.lang.Integer.parseInt(Unknown Source) at java.lang.Integer.valueOf(Unknown Source) at Vyjimka.ctiInt(Vyjimka.java:12) at Vyjimka.main(Vyjimka.java:31)
Seskupování výjimek a postupná selekce Pokud potřebujeme v daném bloku reagovat na více výjimek je možné použít více bloků catch za jedním příkazem try – pozor závisí na pořadí bloků – jakmile vzniklá výjimka vyhovuje třídě výjimek uvedené v catch tak se ostatní bloky neprohledávají. Př. try { ….. } catch (NumberFormatException e) { // zpracuje konkrétní výjimku třídy RuntimeException } catch (RuntimeException e) { // reaguje na zbývající výjimky této třídy }
Vyvolání výjimky Pokud chceme vyzkoušet zda náš program správně reaguje na výjimku je možné ji programově vyvolat (kdekoliv) příkazem throw Př. import java.io.*; public class Vyjimka { public static int ctiInt() throws IOException { byte[] pole = new byte[20]; String nacteno; int i;
try { System.in.read(pole); nacteno = new String(pole).trim(); i = Integer.valueOf(nacteno).intValue(); if (i == 0) throw new IOException(); return i; } catch (IOException e) { System.out.println("Chyba cteni"); throw e; } }
public static void main(String[] argv) { System.out.print("Zadej pocet cihel: "); try { int i = ctiInt(); System.out.println("Cihel je: " + i); } catch (IOException e) { System.out.println("Program neprobehl spravne"); } } }
Konstrukce try-catch-finally • Používá se tehdy, pokud chceme, aby se určitýúsek programu provedl jak v případě výjimky tak v případě normálního úseku programu. Syntaxe : try { // hlídaný blok } catch ( TypVýjimky ) { // ošetření výjimky } finally { // tento kód se provede vždy }
Try-catch-finally • Blok finally se provádíi v případě, že v blocích try nebo catch je : • příkaz return • vyvolána jiná vyjimka Použití: uzavírání otevřených souborů ( v případě neuzavření souboru hrozí ztráta dat) Podobným způsobem funguje konstrukce try-finally