Vaše jistota na trhu IT Výjimky Rudolf Pecinovský [email protected] Vaše jistota na trhu IT Obsah s odkazy ►Výjimky ►Výjimky kontrolované a nekontrolované ►Definice vlastních výjimek Vaše jistota na trhu.
Download ReportTranscript Vaše jistota na trhu IT Výjimky Rudolf Pecinovský [email protected] Vaše jistota na trhu IT Obsah s odkazy ►Výjimky ►Výjimky kontrolované a nekontrolované ►Definice vlastních výjimek Vaše jistota na trhu.
Slide 1
Vaše jistota na trhu IT
Výjimky
Rudolf Pecinovský
[email protected]
Vaše jistota na trhu IT
Obsah s odkazy
►Výjimky
►Výjimky kontrolované a nekontrolované
►Definice vlastních výjimek
Vaše jistota na trhu IT
Výjimky
►Výjimečné situace v programech
►Ošetření nestandardních situací v Javě
►Zpráva o výjimce
►Klíčová slova
►Činnost
►Vyvolání
Výjimečné situace v programech
► V každém programu je alespoň jedna chyba –
program na ni musí být připraven
► Starší programy
● Program vypsal chybové hlášení a ukončil činnost;
● V některých situacích (válcovací stolice, autopilot, …) nepřijatelné
● Funkce vrátí hodnotu signalizující chybu
● Programátor musí neustále testovat, co funkce vrací
● Knihovna měla pro tyto účely vyhrazenu speciální proměnnou,
do níž se v případě chyby zapsal její kód; nahlédnutím do proměnné
program zjistil kód poslední chyby
● Programátor musí neustále testovat, jaká je v proměnné hodnota
► Některé jazyky (Cobol, PL/1, …) proto přišly s koncepcí
ošetření nestandardních situací
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
4
Ošetření nestandardních situací v Javě
► Výjimečná událost =
problém, který brání dalšímu vykonávání části kódu
► Událost je výjimečná v tom, že na rozdíl od běžných problémů
nemá program k vyřešení situace dost informaci
► Program může při výskytu výjimečné události vyvolat výjimku
► Výjimka (exception)
objekt určený k přenosu informací o nastalém problému
z místa jeho vzniku do místa, kde bude problém řešen
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
5
Postup při vyvolání výjimky
1. Vytvoří se výjimka = objekt typu Throwable
(prakticky vždy instance některého z potomků)
2. Vytvořená výjimka se vyhodí =
přeruší se běh programu v místě, kde výjimka vznikla,
a začne se hledat místo, kde bude daná výjimka ošetřena
3. Ošetření výjimky (handler) by mělo uvést program do stavu,
v němž může jeho vykonávání pokračovat
► Výjimka „probublává“ programem z místa vyhození stále výše
a nenarazí-li cestou nikde na své ošetření,
zachytí ji virtuální stroj, který na standardní chybový výstup
vypíše zprávu o vzniku výjimky
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
6
Systémová zpráva o vzniku výjimky
Zpráva o vzniku výjimky spolu s názvem vlákna,
v němž k výjimce došlo (zde AWT-EventQueue-0)
Popis druhu výjimky (aritmetická výjimka dělení nulou)
Informace o místě, odkud byla volána metoda,
která vyvolala metodu, v níž došlo k vyhození výjimky
Informace o místě, odkud byla volána metoda,
v níž došlo k vyhození výjimky
Úplný název třídy včetně balíčku
Copyright © 2006, Rudolf Pecinovský
Název metody
VŠE – 05
Název souboru se
zdrojovým kódem
Číslo řádku zdrojáku,
kde došlo k výjimce
7
Klíčová slova související s výjimkami
► try (zkus)
Označuje blok kódu, v němž může dojít k výjimce
► throw (hoď)
Příkaz k vyhození výjimky;
musí být následován odkazem na existující instanci
► catch (chyť)
Blok ošetřující výjimku, která je zadána jako parametr
► finally (na konec)
Blok s povinnými závěrečnými akcemi nezávisejícími
na případném vzniku výjimky
► throws (hází)
Uvození seznamu výjimek vyhazovaných danou metodou
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
8
Vyvolání a ošetření výjimky v kódu
try {
//Kód, který může vyvolat výjimky
}
catch( Typ1 id1 ) {
//Ošetření výjimek typu Typ1
}
...
catch( TypN idN ) {
//ošetření výjimek typu TypN
}
finally {
//Kód, který se na závěr VŽDY provede
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
9
Náznak činnosti – řádný průběh
nedojde k vyvolání výjimky
= nedojde k chybě
try {
příkaz1();
příkaz2();
příkaz3();
}
catch ( xxxException e ) {
příkazProOšetřeníChyby();
}
Bloky catch
catch (…..
se přeskočí
finally {
ukončovacíPříkazy();
}
dalšíPříkaz();
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
12
Náznak činnosti – ošetřený výjimka
try {
příkaz1(); Při provádění metody příkaz2
dojde k ošetřené chybě
příkaz2();
příkaz3();
Byla vyhozena výjimka
tohoto typu nebo typu
}
některého z potomků
catch ( xxxException e ) {
příkazProOšetřeníChyby();
}
Ostatní bloky catch
catch (…..
se přeskočí
finally {
ukončovacíPříkazy();
}
dalšíPříkaz();
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
13
Náznak činnosti – neošetřená výjimka
Při provádění metody příkaz2
dojde k NEošetřené chybě
try {
příkaz1();
příkaz2();
příkaz3();
}
catch ( xxxException e ) {
příkazProOšetřeníChyby();
}
Ošetření nebylo nalezeno =>
catch (…..
provede se blok finally
a opouští se metoda
finally {
ukončovacíPříkazy();
}
dalšíPříkaz();
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
14
Vyvolání výjimky
public class Xyz implements Comparable
{
public bolean compareTo( Object o )
{
if( !(o instanceOf Xyz) )
throw new ClassCastException (
"\nPokus o porovnání s neporovnatelnou"
+ " instancí " + o );
//Zjištění, kdo je větší
return vysledek;
}
}
► Instanci nemusíme vytvářet až v příkazu throw,
můžeme ji vytvořit kdykoliv před tím a pak mu ji jen předat
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
15
Vaše jistota na trhu IT
Výjimky kontrolované a
nekontrolované
►Hierarchie výjimek
►Pořadí výjimek v blocích catch
►Metody generující výjimky
►Metody třídy Throwable
►Zřetězené výjimky
►Převod kontrolovaných na nekontrolované
Charakteristika
► Výjimky, které jsou potomky třídy RuntimeException
nebo Error označujeme jako nekontrolované (unchecked),
protože překladač nekontroluje, zda je na ně program připraven
► Ostatní výjimky označujeme jako kontrolované (checked),
protože překladač kontroluje dodržení pravidel:
● Každá metoda, která může vyhodit kontrolovanou výjimku,
se musí k této skutečnosti veřejně přihlásit
● Každé použití metody, která může vyhodit kontrolovanou výjimku,
musí být buď uzavřeno v bloku try…catch,
nebo se volající metoda musí přihlásit k tomu,
že může také vyhodit danou kontrolovanou výjimku
► Nekontrolované výjimky ohlašují chyby v programu,
kontrolované výjimky očekávatelné situace,
na jejichž výskyt má být program připraven
a měl by na ně umět reagovat
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
17
Hierarchie výjimek
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
18
Pořadí výjimek v blocích catch
► Třída NumberFormatException
je potomkem třídy RuntimeException
try {
Syntaktická chyba,
......
na druhý blok catch nikdy nedojde
}
catch (RuntimeException e) {
.........
}
Obrácené pořadí bloků catch
catch (NumberFormatException e){
vše vyřeší
........
try {
}
......
}
catch (NumberFormatException e) {
.........
}
catch (RuntimeException e){
........
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
19
Metody generující výjimky
► Java vyžaduje, aby programy, které používají metody
schopné vyvolat kontrolované výjimky,
byly o této schopnosti používaných metod informovány =>
pak vědí, které výjimku musí umět zachytit a ošetřit
► Všechny kontrolované výjimky, které může metoda vyhodit,
musí deklarovat v hlavičce za klíčovým slovem throws
► Deklarace vyhazování nekontrolovaných výjimek není povinná
public void metoda()
throws KontrolovanáVýjimka1,
KontrolovanáVýjimka2
{
// Tělo metody
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
20
Metody třídy Throwable
► String getMessage()
Vrátí zprávu popisující danou výjimku
► String toString()
Vrátí název třídy výjimky následovaný případnou zprávou
► void printStackTrace()
Vytiskne toString() následovaný sadou informací o volající
posloupnosti, která vedla k vzniku výjimky
► Throwable fillInStackTrace()
Připraví nové informace o volací posloupnosti
vedoucí k místu zavolání této metody
► StackTraceElement[] getStackTrace()
Vrátí uchované informace o volací posloupnosti dané výjimky
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
21
Zřetězené výjimky
► V některých situacích je vhodné v rámci ošetření výjimky vyvolat
jinou výjimku, a přitom umožnit zjistit,
která výjimka byla prvotním hybatelem celé akce
► Řada výjimek má mezi svými konstruktory i takové,
které akceptují jako poslední parametr
odkaz na výjimku, jež byla příčinou vyvolání dané výjimky
► Chce-li se program zeptat výjimky na výjimku, která ji způsobila,
použije metodu
public Throwable getCause()
► Ve zprávě o vyvolání výjimky jsou místa, kde byla jedna výjimka
nahrazena jinou, označována textem caused by:
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
22
Ukázka výpisu při zřetězení výjimek
HighLevelException: MidLevelException: LowLevelException
at Junk.a(Junk.java:13)
at Junk.main(Junk.java:4)
Caused by: MidLevelException: LowLevelException
at Junk.c(Junk.java:23)
at Junk.b(Junk.java:17)
at Junk.a(Junk.java:11)
... 1 more
Caused by: LowLevelException
at Junk.e(Junk.java:30)
at Junk.d(Junk.java:27)
at Junk.c(Junk.java:21)
... 3 more
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
23
Převod kontrolovaných na nekontrolované
► Ošetřování kontrolovaných výjimek obtěžuje
► Víme-li, že k dané výjimce nejspíš nedojde
a ošetřujeme-li ji pouze proto, že na tom překladač trvá,
můžeme pro případ, že by k výjimce přece jenom došlo
zaměnit kontrolovanou výjimku za nekontrolovanou
public void prevod( String s ) {
try {
prověř( s );
} catch( Exception ex ) {
throw new RuntimeException( " Neprověřeno! ", ex );
}
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
24
Vaše jistota na trhu IT
Definice vlastních výjimek
►Hierarchie výjimek
►Pořadí výjimek v blocích catch
►Metody generující výjimky
►Metody třídy Throwable
►Vlastní výjimky
►Zásady správného používání výjimek
Definice vlastních výjimek
► Výjimky jsou zcela běžné třídy;
považujeme-li to proto za vhodné, můžeme definovat i vlastní
► Před definicí nové výjimky bychom si měli ujasnit,
bude-li kontrolovaná či nekontrolovaná;
podle toho definujeme jejího předka
► Název výjimek končí dle konvencí slovem Exception
před nímž je naznačena podstata dané výjimky
● IllegalArgumetnException
● NoSuchMethodException
● BadStringOperationException
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
26
Příklad vlastní kontrolované výjimky
public class VelkýPrůšvihException
extends Exception
{
public VelkýPrůšvihException() {};
public VelkýPrůšvihException( String zpráva ) {
super( zpráva );
}
public VelkýPrůšvihException(String zpráva,
Throwable původce ) {
super( zpráva, původce );
}
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
27
Test správného vyhození výjimky
► Na vytvářených programech je třeba otestovat i to,
že v definovaných situacích vyhodí požadovanou výjimku
public void testVyhozeníVýjimky()
{
try {
metodaKteráMáVyhoditVýjimku();
} catch ( VelkýPrůšvihException vpe ) {
return;
}
fail( "Nebyla vyhozena výjimka VelkýPrůšvihException" );
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
28
Zásady správného používání výjimek
1/2
Neignorujte
výjimky
try {
//Nějaký kód
}
catch(Exception e){}
► Výjimky, o nichž víte, že nemohou nastat,
převeďte na nekontrolované pro případ,
že by v budoucích verzích programu nastat mohly
► Při ošetřování výjimek, které nastat mohou,
ale nemají vliv na chod programu,
vložte do těla ošetření alespoň vysvětlující komentář
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
29
Zásady správného používání výjimek
2/2
► Používejte výjimky pouze k ošetření výjimečných stavů
► Kontrolované výjimky používejte u stavů, z nichž se lze zotavit,
jinak použijte výjimky nekontrolované
► Vyhýbejte se zbytečnému používání kontrolovaných výjimek
● Programátory ošetřování kontrolovaných výjimek obtěžuje
a mají pak tendenci je ošetřovat prázdným blokem catch
► Dávejte přednost standardním výjimkám,
vyvolávejte výjimky odpovídající dané abstrakci
● Programátoři by měli z názvu výjimky poznat, co se stalo
● Standardní výjimky mají všeobecně známý význam
► Snažte se o atomičnost selhání; i po vyhození výjimky
by měl být objekt v dobře definovaném stavu
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
30
Zásady správného používání výjimek
3/2
► Doplňujte výjimky zprávami,
výjimka by sama měla poskytnout dostatek informací
a neměla by programátora nutit k podrobnější analýze programu
► Dokumentujte vyvolávané výjimky v dokumentačních
komentářích pomocí značky @throws
► Nedělejte bloky try zbytečně velké,
kód uvnitř těchto bloků se neoptimalizuje
► Umíte-li výjimku v metodě ošetřit, udělejte to
► Detekuje-li se chyba v jedné metodě a má se ošetřit v jiné
(stejné či jiné instance), použijte výjimku.
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
31
Nejčastěji používané výjimky
1/2
► IllegalArgumentException
Byla zadána nepovolená hodnota parametru
● Např. chci nastavit zápornou velikost grafického tvaru
► IllegalStateException
V daném stavu objektu nelze metodu provést
● Např. otevřu soubor, přečtu pár vět, zavřu soubor a chci znovu přečíst větu
► NullPointerException
Byla vyvolána metoda instance, na níž ukazuje prázdný odkaz,
nebo byl předán nepovolený prázdný odkaz v parametru
► ArrayIndexOutOfBoundException
Byly zadány špatné meze pole, buď záporné nebo moc velké
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
32
Nejčastěji používané výjimky
2/2
► ConcurrentModificationException
V průběhu iterace byla změněna struktura kontejneru
● Např. byl do kontejneru přidán prvek
► NumberFormatException
Je požadován špatný převod řetězce na číslo či naopak
● Chci-li např. převést na číslo řetězec, který není číslem
● Častá chyba v metodách String.format či PrintStream.printf
► ClassCastException
Požadované přetypování není možné
► UnsupportedOperationException
Požadovaná operace není podporována
(např. chci přidat prvek do neměnného kontejneru)
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
33
Vaše jistota na trhu IT
Děkuji za pozornost
►Rudolf Pecinovský
http://vyuka.pecinovsky.cz/vse
mail: [email protected]
ICQ: 158 156 600
Slide 2
Vaše jistota na trhu IT
Výjimky
Rudolf Pecinovský
[email protected]
Vaše jistota na trhu IT
Obsah s odkazy
►Výjimky
►Výjimky kontrolované a nekontrolované
►Definice vlastních výjimek
Vaše jistota na trhu IT
Výjimky
►Výjimečné situace v programech
►Ošetření nestandardních situací v Javě
►Zpráva o výjimce
►Klíčová slova
►Činnost
►Vyvolání
Výjimečné situace v programech
► V každém programu je alespoň jedna chyba –
program na ni musí být připraven
► Starší programy
● Program vypsal chybové hlášení a ukončil činnost;
● V některých situacích (válcovací stolice, autopilot, …) nepřijatelné
● Funkce vrátí hodnotu signalizující chybu
● Programátor musí neustále testovat, co funkce vrací
● Knihovna měla pro tyto účely vyhrazenu speciální proměnnou,
do níž se v případě chyby zapsal její kód; nahlédnutím do proměnné
program zjistil kód poslední chyby
● Programátor musí neustále testovat, jaká je v proměnné hodnota
► Některé jazyky (Cobol, PL/1, …) proto přišly s koncepcí
ošetření nestandardních situací
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
4
Ošetření nestandardních situací v Javě
► Výjimečná událost =
problém, který brání dalšímu vykonávání části kódu
► Událost je výjimečná v tom, že na rozdíl od běžných problémů
nemá program k vyřešení situace dost informaci
► Program může při výskytu výjimečné události vyvolat výjimku
► Výjimka (exception)
objekt určený k přenosu informací o nastalém problému
z místa jeho vzniku do místa, kde bude problém řešen
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
5
Postup při vyvolání výjimky
1. Vytvoří se výjimka = objekt typu Throwable
(prakticky vždy instance některého z potomků)
2. Vytvořená výjimka se vyhodí =
přeruší se běh programu v místě, kde výjimka vznikla,
a začne se hledat místo, kde bude daná výjimka ošetřena
3. Ošetření výjimky (handler) by mělo uvést program do stavu,
v němž může jeho vykonávání pokračovat
► Výjimka „probublává“ programem z místa vyhození stále výše
a nenarazí-li cestou nikde na své ošetření,
zachytí ji virtuální stroj, který na standardní chybový výstup
vypíše zprávu o vzniku výjimky
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
6
Systémová zpráva o vzniku výjimky
Zpráva o vzniku výjimky spolu s názvem vlákna,
v němž k výjimce došlo (zde AWT-EventQueue-0)
Popis druhu výjimky (aritmetická výjimka dělení nulou)
Informace o místě, odkud byla volána metoda,
která vyvolala metodu, v níž došlo k vyhození výjimky
Informace o místě, odkud byla volána metoda,
v níž došlo k vyhození výjimky
Úplný název třídy včetně balíčku
Copyright © 2006, Rudolf Pecinovský
Název metody
VŠE – 05
Název souboru se
zdrojovým kódem
Číslo řádku zdrojáku,
kde došlo k výjimce
7
Klíčová slova související s výjimkami
► try (zkus)
Označuje blok kódu, v němž může dojít k výjimce
► throw (hoď)
Příkaz k vyhození výjimky;
musí být následován odkazem na existující instanci
► catch (chyť)
Blok ošetřující výjimku, která je zadána jako parametr
► finally (na konec)
Blok s povinnými závěrečnými akcemi nezávisejícími
na případném vzniku výjimky
► throws (hází)
Uvození seznamu výjimek vyhazovaných danou metodou
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
8
Vyvolání a ošetření výjimky v kódu
try {
//Kód, který může vyvolat výjimky
}
catch( Typ1 id1 ) {
//Ošetření výjimek typu Typ1
}
...
catch( TypN idN ) {
//ošetření výjimek typu TypN
}
finally {
//Kód, který se na závěr VŽDY provede
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
9
Náznak činnosti – řádný průběh
nedojde k vyvolání výjimky
= nedojde k chybě
try {
příkaz1();
příkaz2();
příkaz3();
}
catch ( xxxException e ) {
příkazProOšetřeníChyby();
}
Bloky catch
catch (…..
se přeskočí
finally {
ukončovacíPříkazy();
}
dalšíPříkaz();
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
12
Náznak činnosti – ošetřený výjimka
try {
příkaz1(); Při provádění metody příkaz2
dojde k ošetřené chybě
příkaz2();
příkaz3();
Byla vyhozena výjimka
tohoto typu nebo typu
}
některého z potomků
catch ( xxxException e ) {
příkazProOšetřeníChyby();
}
Ostatní bloky catch
catch (…..
se přeskočí
finally {
ukončovacíPříkazy();
}
dalšíPříkaz();
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
13
Náznak činnosti – neošetřená výjimka
Při provádění metody příkaz2
dojde k NEošetřené chybě
try {
příkaz1();
příkaz2();
příkaz3();
}
catch ( xxxException e ) {
příkazProOšetřeníChyby();
}
Ošetření nebylo nalezeno =>
catch (…..
provede se blok finally
a opouští se metoda
finally {
ukončovacíPříkazy();
}
dalšíPříkaz();
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
14
Vyvolání výjimky
public class Xyz implements Comparable
{
public bolean compareTo( Object o )
{
if( !(o instanceOf Xyz) )
throw new ClassCastException (
"\nPokus o porovnání s neporovnatelnou"
+ " instancí " + o );
//Zjištění, kdo je větší
return vysledek;
}
}
► Instanci nemusíme vytvářet až v příkazu throw,
můžeme ji vytvořit kdykoliv před tím a pak mu ji jen předat
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
15
Vaše jistota na trhu IT
Výjimky kontrolované a
nekontrolované
►Hierarchie výjimek
►Pořadí výjimek v blocích catch
►Metody generující výjimky
►Metody třídy Throwable
►Zřetězené výjimky
►Převod kontrolovaných na nekontrolované
Charakteristika
► Výjimky, které jsou potomky třídy RuntimeException
nebo Error označujeme jako nekontrolované (unchecked),
protože překladač nekontroluje, zda je na ně program připraven
► Ostatní výjimky označujeme jako kontrolované (checked),
protože překladač kontroluje dodržení pravidel:
● Každá metoda, která může vyhodit kontrolovanou výjimku,
se musí k této skutečnosti veřejně přihlásit
● Každé použití metody, která může vyhodit kontrolovanou výjimku,
musí být buď uzavřeno v bloku try…catch,
nebo se volající metoda musí přihlásit k tomu,
že může také vyhodit danou kontrolovanou výjimku
► Nekontrolované výjimky ohlašují chyby v programu,
kontrolované výjimky očekávatelné situace,
na jejichž výskyt má být program připraven
a měl by na ně umět reagovat
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
17
Hierarchie výjimek
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
18
Pořadí výjimek v blocích catch
► Třída NumberFormatException
je potomkem třídy RuntimeException
try {
Syntaktická chyba,
......
na druhý blok catch nikdy nedojde
}
catch (RuntimeException e) {
.........
}
Obrácené pořadí bloků catch
catch (NumberFormatException e){
vše vyřeší
........
try {
}
......
}
catch (NumberFormatException e) {
.........
}
catch (RuntimeException e){
........
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
19
Metody generující výjimky
► Java vyžaduje, aby programy, které používají metody
schopné vyvolat kontrolované výjimky,
byly o této schopnosti používaných metod informovány =>
pak vědí, které výjimku musí umět zachytit a ošetřit
► Všechny kontrolované výjimky, které může metoda vyhodit,
musí deklarovat v hlavičce za klíčovým slovem throws
► Deklarace vyhazování nekontrolovaných výjimek není povinná
public void metoda()
throws KontrolovanáVýjimka1,
KontrolovanáVýjimka2
{
// Tělo metody
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
20
Metody třídy Throwable
► String getMessage()
Vrátí zprávu popisující danou výjimku
► String toString()
Vrátí název třídy výjimky následovaný případnou zprávou
► void printStackTrace()
Vytiskne toString() následovaný sadou informací o volající
posloupnosti, která vedla k vzniku výjimky
► Throwable fillInStackTrace()
Připraví nové informace o volací posloupnosti
vedoucí k místu zavolání této metody
► StackTraceElement[] getStackTrace()
Vrátí uchované informace o volací posloupnosti dané výjimky
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
21
Zřetězené výjimky
► V některých situacích je vhodné v rámci ošetření výjimky vyvolat
jinou výjimku, a přitom umožnit zjistit,
která výjimka byla prvotním hybatelem celé akce
► Řada výjimek má mezi svými konstruktory i takové,
které akceptují jako poslední parametr
odkaz na výjimku, jež byla příčinou vyvolání dané výjimky
► Chce-li se program zeptat výjimky na výjimku, která ji způsobila,
použije metodu
public Throwable getCause()
► Ve zprávě o vyvolání výjimky jsou místa, kde byla jedna výjimka
nahrazena jinou, označována textem caused by:
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
22
Ukázka výpisu při zřetězení výjimek
HighLevelException: MidLevelException: LowLevelException
at Junk.a(Junk.java:13)
at Junk.main(Junk.java:4)
Caused by: MidLevelException: LowLevelException
at Junk.c(Junk.java:23)
at Junk.b(Junk.java:17)
at Junk.a(Junk.java:11)
... 1 more
Caused by: LowLevelException
at Junk.e(Junk.java:30)
at Junk.d(Junk.java:27)
at Junk.c(Junk.java:21)
... 3 more
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
23
Převod kontrolovaných na nekontrolované
► Ošetřování kontrolovaných výjimek obtěžuje
► Víme-li, že k dané výjimce nejspíš nedojde
a ošetřujeme-li ji pouze proto, že na tom překladač trvá,
můžeme pro případ, že by k výjimce přece jenom došlo
zaměnit kontrolovanou výjimku za nekontrolovanou
public void prevod( String s ) {
try {
prověř( s );
} catch( Exception ex ) {
throw new RuntimeException( " Neprověřeno! ", ex );
}
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
24
Vaše jistota na trhu IT
Definice vlastních výjimek
►Hierarchie výjimek
►Pořadí výjimek v blocích catch
►Metody generující výjimky
►Metody třídy Throwable
►Vlastní výjimky
►Zásady správného používání výjimek
Definice vlastních výjimek
► Výjimky jsou zcela běžné třídy;
považujeme-li to proto za vhodné, můžeme definovat i vlastní
► Před definicí nové výjimky bychom si měli ujasnit,
bude-li kontrolovaná či nekontrolovaná;
podle toho definujeme jejího předka
► Název výjimek končí dle konvencí slovem Exception
před nímž je naznačena podstata dané výjimky
● IllegalArgumetnException
● NoSuchMethodException
● BadStringOperationException
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
26
Příklad vlastní kontrolované výjimky
public class VelkýPrůšvihException
extends Exception
{
public VelkýPrůšvihException() {};
public VelkýPrůšvihException( String zpráva ) {
super( zpráva );
}
public VelkýPrůšvihException(String zpráva,
Throwable původce ) {
super( zpráva, původce );
}
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
27
Test správného vyhození výjimky
► Na vytvářených programech je třeba otestovat i to,
že v definovaných situacích vyhodí požadovanou výjimku
public void testVyhozeníVýjimky()
{
try {
metodaKteráMáVyhoditVýjimku();
} catch ( VelkýPrůšvihException vpe ) {
return;
}
fail( "Nebyla vyhozena výjimka VelkýPrůšvihException" );
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
28
Zásady správného používání výjimek
1/2
Neignorujte
výjimky
try {
//Nějaký kód
}
catch(Exception e){}
► Výjimky, o nichž víte, že nemohou nastat,
převeďte na nekontrolované pro případ,
že by v budoucích verzích programu nastat mohly
► Při ošetřování výjimek, které nastat mohou,
ale nemají vliv na chod programu,
vložte do těla ošetření alespoň vysvětlující komentář
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
29
Zásady správného používání výjimek
2/2
► Používejte výjimky pouze k ošetření výjimečných stavů
► Kontrolované výjimky používejte u stavů, z nichž se lze zotavit,
jinak použijte výjimky nekontrolované
► Vyhýbejte se zbytečnému používání kontrolovaných výjimek
● Programátory ošetřování kontrolovaných výjimek obtěžuje
a mají pak tendenci je ošetřovat prázdným blokem catch
► Dávejte přednost standardním výjimkám,
vyvolávejte výjimky odpovídající dané abstrakci
● Programátoři by měli z názvu výjimky poznat, co se stalo
● Standardní výjimky mají všeobecně známý význam
► Snažte se o atomičnost selhání; i po vyhození výjimky
by měl být objekt v dobře definovaném stavu
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
30
Zásady správného používání výjimek
3/2
► Doplňujte výjimky zprávami,
výjimka by sama měla poskytnout dostatek informací
a neměla by programátora nutit k podrobnější analýze programu
► Dokumentujte vyvolávané výjimky v dokumentačních
komentářích pomocí značky @throws
► Nedělejte bloky try zbytečně velké,
kód uvnitř těchto bloků se neoptimalizuje
► Umíte-li výjimku v metodě ošetřit, udělejte to
► Detekuje-li se chyba v jedné metodě a má se ošetřit v jiné
(stejné či jiné instance), použijte výjimku.
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
31
Nejčastěji používané výjimky
1/2
► IllegalArgumentException
Byla zadána nepovolená hodnota parametru
● Např. chci nastavit zápornou velikost grafického tvaru
► IllegalStateException
V daném stavu objektu nelze metodu provést
● Např. otevřu soubor, přečtu pár vět, zavřu soubor a chci znovu přečíst větu
► NullPointerException
Byla vyvolána metoda instance, na níž ukazuje prázdný odkaz,
nebo byl předán nepovolený prázdný odkaz v parametru
► ArrayIndexOutOfBoundException
Byly zadány špatné meze pole, buď záporné nebo moc velké
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
32
Nejčastěji používané výjimky
2/2
► ConcurrentModificationException
V průběhu iterace byla změněna struktura kontejneru
● Např. byl do kontejneru přidán prvek
► NumberFormatException
Je požadován špatný převod řetězce na číslo či naopak
● Chci-li např. převést na číslo řetězec, který není číslem
● Častá chyba v metodách String.format či PrintStream.printf
► ClassCastException
Požadované přetypování není možné
► UnsupportedOperationException
Požadovaná operace není podporována
(např. chci přidat prvek do neměnného kontejneru)
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
33
Vaše jistota na trhu IT
Děkuji za pozornost
►Rudolf Pecinovský
http://vyuka.pecinovsky.cz/vse
mail: [email protected]
ICQ: 158 156 600
Slide 3
Vaše jistota na trhu IT
Výjimky
Rudolf Pecinovský
[email protected]
Vaše jistota na trhu IT
Obsah s odkazy
►Výjimky
►Výjimky kontrolované a nekontrolované
►Definice vlastních výjimek
Vaše jistota na trhu IT
Výjimky
►Výjimečné situace v programech
►Ošetření nestandardních situací v Javě
►Zpráva o výjimce
►Klíčová slova
►Činnost
►Vyvolání
Výjimečné situace v programech
► V každém programu je alespoň jedna chyba –
program na ni musí být připraven
► Starší programy
● Program vypsal chybové hlášení a ukončil činnost;
● V některých situacích (válcovací stolice, autopilot, …) nepřijatelné
● Funkce vrátí hodnotu signalizující chybu
● Programátor musí neustále testovat, co funkce vrací
● Knihovna měla pro tyto účely vyhrazenu speciální proměnnou,
do níž se v případě chyby zapsal její kód; nahlédnutím do proměnné
program zjistil kód poslední chyby
● Programátor musí neustále testovat, jaká je v proměnné hodnota
► Některé jazyky (Cobol, PL/1, …) proto přišly s koncepcí
ošetření nestandardních situací
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
4
Ošetření nestandardních situací v Javě
► Výjimečná událost =
problém, který brání dalšímu vykonávání části kódu
► Událost je výjimečná v tom, že na rozdíl od běžných problémů
nemá program k vyřešení situace dost informaci
► Program může při výskytu výjimečné události vyvolat výjimku
► Výjimka (exception)
objekt určený k přenosu informací o nastalém problému
z místa jeho vzniku do místa, kde bude problém řešen
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
5
Postup při vyvolání výjimky
1. Vytvoří se výjimka = objekt typu Throwable
(prakticky vždy instance některého z potomků)
2. Vytvořená výjimka se vyhodí =
přeruší se běh programu v místě, kde výjimka vznikla,
a začne se hledat místo, kde bude daná výjimka ošetřena
3. Ošetření výjimky (handler) by mělo uvést program do stavu,
v němž může jeho vykonávání pokračovat
► Výjimka „probublává“ programem z místa vyhození stále výše
a nenarazí-li cestou nikde na své ošetření,
zachytí ji virtuální stroj, který na standardní chybový výstup
vypíše zprávu o vzniku výjimky
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
6
Systémová zpráva o vzniku výjimky
Zpráva o vzniku výjimky spolu s názvem vlákna,
v němž k výjimce došlo (zde AWT-EventQueue-0)
Popis druhu výjimky (aritmetická výjimka dělení nulou)
Informace o místě, odkud byla volána metoda,
která vyvolala metodu, v níž došlo k vyhození výjimky
Informace o místě, odkud byla volána metoda,
v níž došlo k vyhození výjimky
Úplný název třídy včetně balíčku
Copyright © 2006, Rudolf Pecinovský
Název metody
VŠE – 05
Název souboru se
zdrojovým kódem
Číslo řádku zdrojáku,
kde došlo k výjimce
7
Klíčová slova související s výjimkami
► try (zkus)
Označuje blok kódu, v němž může dojít k výjimce
► throw (hoď)
Příkaz k vyhození výjimky;
musí být následován odkazem na existující instanci
► catch (chyť)
Blok ošetřující výjimku, která je zadána jako parametr
► finally (na konec)
Blok s povinnými závěrečnými akcemi nezávisejícími
na případném vzniku výjimky
► throws (hází)
Uvození seznamu výjimek vyhazovaných danou metodou
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
8
Vyvolání a ošetření výjimky v kódu
try {
//Kód, který může vyvolat výjimky
}
catch( Typ1 id1 ) {
//Ošetření výjimek typu Typ1
}
...
catch( TypN idN ) {
//ošetření výjimek typu TypN
}
finally {
//Kód, který se na závěr VŽDY provede
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
9
Náznak činnosti – řádný průběh
nedojde k vyvolání výjimky
= nedojde k chybě
try {
příkaz1();
příkaz2();
příkaz3();
}
catch ( xxxException e ) {
příkazProOšetřeníChyby();
}
Bloky catch
catch (…..
se přeskočí
finally {
ukončovacíPříkazy();
}
dalšíPříkaz();
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
12
Náznak činnosti – ošetřený výjimka
try {
příkaz1(); Při provádění metody příkaz2
dojde k ošetřené chybě
příkaz2();
příkaz3();
Byla vyhozena výjimka
tohoto typu nebo typu
}
některého z potomků
catch ( xxxException e ) {
příkazProOšetřeníChyby();
}
Ostatní bloky catch
catch (…..
se přeskočí
finally {
ukončovacíPříkazy();
}
dalšíPříkaz();
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
13
Náznak činnosti – neošetřená výjimka
Při provádění metody příkaz2
dojde k NEošetřené chybě
try {
příkaz1();
příkaz2();
příkaz3();
}
catch ( xxxException e ) {
příkazProOšetřeníChyby();
}
Ošetření nebylo nalezeno =>
catch (…..
provede se blok finally
a opouští se metoda
finally {
ukončovacíPříkazy();
}
dalšíPříkaz();
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
14
Vyvolání výjimky
public class Xyz implements Comparable
{
public bolean compareTo( Object o )
{
if( !(o instanceOf Xyz) )
throw new ClassCastException (
"\nPokus o porovnání s neporovnatelnou"
+ " instancí " + o );
//Zjištění, kdo je větší
return vysledek;
}
}
► Instanci nemusíme vytvářet až v příkazu throw,
můžeme ji vytvořit kdykoliv před tím a pak mu ji jen předat
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
15
Vaše jistota na trhu IT
Výjimky kontrolované a
nekontrolované
►Hierarchie výjimek
►Pořadí výjimek v blocích catch
►Metody generující výjimky
►Metody třídy Throwable
►Zřetězené výjimky
►Převod kontrolovaných na nekontrolované
Charakteristika
► Výjimky, které jsou potomky třídy RuntimeException
nebo Error označujeme jako nekontrolované (unchecked),
protože překladač nekontroluje, zda je na ně program připraven
► Ostatní výjimky označujeme jako kontrolované (checked),
protože překladač kontroluje dodržení pravidel:
● Každá metoda, která může vyhodit kontrolovanou výjimku,
se musí k této skutečnosti veřejně přihlásit
● Každé použití metody, která může vyhodit kontrolovanou výjimku,
musí být buď uzavřeno v bloku try…catch,
nebo se volající metoda musí přihlásit k tomu,
že může také vyhodit danou kontrolovanou výjimku
► Nekontrolované výjimky ohlašují chyby v programu,
kontrolované výjimky očekávatelné situace,
na jejichž výskyt má být program připraven
a měl by na ně umět reagovat
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
17
Hierarchie výjimek
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
18
Pořadí výjimek v blocích catch
► Třída NumberFormatException
je potomkem třídy RuntimeException
try {
Syntaktická chyba,
......
na druhý blok catch nikdy nedojde
}
catch (RuntimeException e) {
.........
}
Obrácené pořadí bloků catch
catch (NumberFormatException e){
vše vyřeší
........
try {
}
......
}
catch (NumberFormatException e) {
.........
}
catch (RuntimeException e){
........
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
19
Metody generující výjimky
► Java vyžaduje, aby programy, které používají metody
schopné vyvolat kontrolované výjimky,
byly o této schopnosti používaných metod informovány =>
pak vědí, které výjimku musí umět zachytit a ošetřit
► Všechny kontrolované výjimky, které může metoda vyhodit,
musí deklarovat v hlavičce za klíčovým slovem throws
► Deklarace vyhazování nekontrolovaných výjimek není povinná
public void metoda()
throws KontrolovanáVýjimka1,
KontrolovanáVýjimka2
{
// Tělo metody
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
20
Metody třídy Throwable
► String getMessage()
Vrátí zprávu popisující danou výjimku
► String toString()
Vrátí název třídy výjimky následovaný případnou zprávou
► void printStackTrace()
Vytiskne toString() následovaný sadou informací o volající
posloupnosti, která vedla k vzniku výjimky
► Throwable fillInStackTrace()
Připraví nové informace o volací posloupnosti
vedoucí k místu zavolání této metody
► StackTraceElement[] getStackTrace()
Vrátí uchované informace o volací posloupnosti dané výjimky
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
21
Zřetězené výjimky
► V některých situacích je vhodné v rámci ošetření výjimky vyvolat
jinou výjimku, a přitom umožnit zjistit,
která výjimka byla prvotním hybatelem celé akce
► Řada výjimek má mezi svými konstruktory i takové,
které akceptují jako poslední parametr
odkaz na výjimku, jež byla příčinou vyvolání dané výjimky
► Chce-li se program zeptat výjimky na výjimku, která ji způsobila,
použije metodu
public Throwable getCause()
► Ve zprávě o vyvolání výjimky jsou místa, kde byla jedna výjimka
nahrazena jinou, označována textem caused by:
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
22
Ukázka výpisu při zřetězení výjimek
HighLevelException: MidLevelException: LowLevelException
at Junk.a(Junk.java:13)
at Junk.main(Junk.java:4)
Caused by: MidLevelException: LowLevelException
at Junk.c(Junk.java:23)
at Junk.b(Junk.java:17)
at Junk.a(Junk.java:11)
... 1 more
Caused by: LowLevelException
at Junk.e(Junk.java:30)
at Junk.d(Junk.java:27)
at Junk.c(Junk.java:21)
... 3 more
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
23
Převod kontrolovaných na nekontrolované
► Ošetřování kontrolovaných výjimek obtěžuje
► Víme-li, že k dané výjimce nejspíš nedojde
a ošetřujeme-li ji pouze proto, že na tom překladač trvá,
můžeme pro případ, že by k výjimce přece jenom došlo
zaměnit kontrolovanou výjimku za nekontrolovanou
public void prevod( String s ) {
try {
prověř( s );
} catch( Exception ex ) {
throw new RuntimeException( " Neprověřeno! ", ex );
}
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
24
Vaše jistota na trhu IT
Definice vlastních výjimek
►Hierarchie výjimek
►Pořadí výjimek v blocích catch
►Metody generující výjimky
►Metody třídy Throwable
►Vlastní výjimky
►Zásady správného používání výjimek
Definice vlastních výjimek
► Výjimky jsou zcela běžné třídy;
považujeme-li to proto za vhodné, můžeme definovat i vlastní
► Před definicí nové výjimky bychom si měli ujasnit,
bude-li kontrolovaná či nekontrolovaná;
podle toho definujeme jejího předka
► Název výjimek končí dle konvencí slovem Exception
před nímž je naznačena podstata dané výjimky
● IllegalArgumetnException
● NoSuchMethodException
● BadStringOperationException
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
26
Příklad vlastní kontrolované výjimky
public class VelkýPrůšvihException
extends Exception
{
public VelkýPrůšvihException() {};
public VelkýPrůšvihException( String zpráva ) {
super( zpráva );
}
public VelkýPrůšvihException(String zpráva,
Throwable původce ) {
super( zpráva, původce );
}
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
27
Test správného vyhození výjimky
► Na vytvářených programech je třeba otestovat i to,
že v definovaných situacích vyhodí požadovanou výjimku
public void testVyhozeníVýjimky()
{
try {
metodaKteráMáVyhoditVýjimku();
} catch ( VelkýPrůšvihException vpe ) {
return;
}
fail( "Nebyla vyhozena výjimka VelkýPrůšvihException" );
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
28
Zásady správného používání výjimek
1/2
Neignorujte
výjimky
try {
//Nějaký kód
}
catch(Exception e){}
► Výjimky, o nichž víte, že nemohou nastat,
převeďte na nekontrolované pro případ,
že by v budoucích verzích programu nastat mohly
► Při ošetřování výjimek, které nastat mohou,
ale nemají vliv na chod programu,
vložte do těla ošetření alespoň vysvětlující komentář
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
29
Zásady správného používání výjimek
2/2
► Používejte výjimky pouze k ošetření výjimečných stavů
► Kontrolované výjimky používejte u stavů, z nichž se lze zotavit,
jinak použijte výjimky nekontrolované
► Vyhýbejte se zbytečnému používání kontrolovaných výjimek
● Programátory ošetřování kontrolovaných výjimek obtěžuje
a mají pak tendenci je ošetřovat prázdným blokem catch
► Dávejte přednost standardním výjimkám,
vyvolávejte výjimky odpovídající dané abstrakci
● Programátoři by měli z názvu výjimky poznat, co se stalo
● Standardní výjimky mají všeobecně známý význam
► Snažte se o atomičnost selhání; i po vyhození výjimky
by měl být objekt v dobře definovaném stavu
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
30
Zásady správného používání výjimek
3/2
► Doplňujte výjimky zprávami,
výjimka by sama měla poskytnout dostatek informací
a neměla by programátora nutit k podrobnější analýze programu
► Dokumentujte vyvolávané výjimky v dokumentačních
komentářích pomocí značky @throws
► Nedělejte bloky try zbytečně velké,
kód uvnitř těchto bloků se neoptimalizuje
► Umíte-li výjimku v metodě ošetřit, udělejte to
► Detekuje-li se chyba v jedné metodě a má se ošetřit v jiné
(stejné či jiné instance), použijte výjimku.
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
31
Nejčastěji používané výjimky
1/2
► IllegalArgumentException
Byla zadána nepovolená hodnota parametru
● Např. chci nastavit zápornou velikost grafického tvaru
► IllegalStateException
V daném stavu objektu nelze metodu provést
● Např. otevřu soubor, přečtu pár vět, zavřu soubor a chci znovu přečíst větu
► NullPointerException
Byla vyvolána metoda instance, na níž ukazuje prázdný odkaz,
nebo byl předán nepovolený prázdný odkaz v parametru
► ArrayIndexOutOfBoundException
Byly zadány špatné meze pole, buď záporné nebo moc velké
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
32
Nejčastěji používané výjimky
2/2
► ConcurrentModificationException
V průběhu iterace byla změněna struktura kontejneru
● Např. byl do kontejneru přidán prvek
► NumberFormatException
Je požadován špatný převod řetězce na číslo či naopak
● Chci-li např. převést na číslo řetězec, který není číslem
● Častá chyba v metodách String.format či PrintStream.printf
► ClassCastException
Požadované přetypování není možné
► UnsupportedOperationException
Požadovaná operace není podporována
(např. chci přidat prvek do neměnného kontejneru)
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
33
Vaše jistota na trhu IT
Děkuji za pozornost
►Rudolf Pecinovský
http://vyuka.pecinovsky.cz/vse
mail: [email protected]
ICQ: 158 156 600
Slide 4
Vaše jistota na trhu IT
Výjimky
Rudolf Pecinovský
[email protected]
Vaše jistota na trhu IT
Obsah s odkazy
►Výjimky
►Výjimky kontrolované a nekontrolované
►Definice vlastních výjimek
Vaše jistota na trhu IT
Výjimky
►Výjimečné situace v programech
►Ošetření nestandardních situací v Javě
►Zpráva o výjimce
►Klíčová slova
►Činnost
►Vyvolání
Výjimečné situace v programech
► V každém programu je alespoň jedna chyba –
program na ni musí být připraven
► Starší programy
● Program vypsal chybové hlášení a ukončil činnost;
● V některých situacích (válcovací stolice, autopilot, …) nepřijatelné
● Funkce vrátí hodnotu signalizující chybu
● Programátor musí neustále testovat, co funkce vrací
● Knihovna měla pro tyto účely vyhrazenu speciální proměnnou,
do níž se v případě chyby zapsal její kód; nahlédnutím do proměnné
program zjistil kód poslední chyby
● Programátor musí neustále testovat, jaká je v proměnné hodnota
► Některé jazyky (Cobol, PL/1, …) proto přišly s koncepcí
ošetření nestandardních situací
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
4
Ošetření nestandardních situací v Javě
► Výjimečná událost =
problém, který brání dalšímu vykonávání části kódu
► Událost je výjimečná v tom, že na rozdíl od běžných problémů
nemá program k vyřešení situace dost informaci
► Program může při výskytu výjimečné události vyvolat výjimku
► Výjimka (exception)
objekt určený k přenosu informací o nastalém problému
z místa jeho vzniku do místa, kde bude problém řešen
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
5
Postup při vyvolání výjimky
1. Vytvoří se výjimka = objekt typu Throwable
(prakticky vždy instance některého z potomků)
2. Vytvořená výjimka se vyhodí =
přeruší se běh programu v místě, kde výjimka vznikla,
a začne se hledat místo, kde bude daná výjimka ošetřena
3. Ošetření výjimky (handler) by mělo uvést program do stavu,
v němž může jeho vykonávání pokračovat
► Výjimka „probublává“ programem z místa vyhození stále výše
a nenarazí-li cestou nikde na své ošetření,
zachytí ji virtuální stroj, který na standardní chybový výstup
vypíše zprávu o vzniku výjimky
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
6
Systémová zpráva o vzniku výjimky
Zpráva o vzniku výjimky spolu s názvem vlákna,
v němž k výjimce došlo (zde AWT-EventQueue-0)
Popis druhu výjimky (aritmetická výjimka dělení nulou)
Informace o místě, odkud byla volána metoda,
která vyvolala metodu, v níž došlo k vyhození výjimky
Informace o místě, odkud byla volána metoda,
v níž došlo k vyhození výjimky
Úplný název třídy včetně balíčku
Copyright © 2006, Rudolf Pecinovský
Název metody
VŠE – 05
Název souboru se
zdrojovým kódem
Číslo řádku zdrojáku,
kde došlo k výjimce
7
Klíčová slova související s výjimkami
► try (zkus)
Označuje blok kódu, v němž může dojít k výjimce
► throw (hoď)
Příkaz k vyhození výjimky;
musí být následován odkazem na existující instanci
► catch (chyť)
Blok ošetřující výjimku, která je zadána jako parametr
► finally (na konec)
Blok s povinnými závěrečnými akcemi nezávisejícími
na případném vzniku výjimky
► throws (hází)
Uvození seznamu výjimek vyhazovaných danou metodou
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
8
Vyvolání a ošetření výjimky v kódu
try {
//Kód, který může vyvolat výjimky
}
catch( Typ1 id1 ) {
//Ošetření výjimek typu Typ1
}
...
catch( TypN idN ) {
//ošetření výjimek typu TypN
}
finally {
//Kód, který se na závěr VŽDY provede
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
9
Náznak činnosti – řádný průběh
nedojde k vyvolání výjimky
= nedojde k chybě
try {
příkaz1();
příkaz2();
příkaz3();
}
catch ( xxxException e ) {
příkazProOšetřeníChyby();
}
Bloky catch
catch (…..
se přeskočí
finally {
ukončovacíPříkazy();
}
dalšíPříkaz();
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
12
Náznak činnosti – ošetřený výjimka
try {
příkaz1(); Při provádění metody příkaz2
dojde k ošetřené chybě
příkaz2();
příkaz3();
Byla vyhozena výjimka
tohoto typu nebo typu
}
některého z potomků
catch ( xxxException e ) {
příkazProOšetřeníChyby();
}
Ostatní bloky catch
catch (…..
se přeskočí
finally {
ukončovacíPříkazy();
}
dalšíPříkaz();
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
13
Náznak činnosti – neošetřená výjimka
Při provádění metody příkaz2
dojde k NEošetřené chybě
try {
příkaz1();
příkaz2();
příkaz3();
}
catch ( xxxException e ) {
příkazProOšetřeníChyby();
}
Ošetření nebylo nalezeno =>
catch (…..
provede se blok finally
a opouští se metoda
finally {
ukončovacíPříkazy();
}
dalšíPříkaz();
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
14
Vyvolání výjimky
public class Xyz implements Comparable
{
public bolean compareTo( Object o )
{
if( !(o instanceOf Xyz) )
throw new ClassCastException (
"\nPokus o porovnání s neporovnatelnou"
+ " instancí " + o );
//Zjištění, kdo je větší
return vysledek;
}
}
► Instanci nemusíme vytvářet až v příkazu throw,
můžeme ji vytvořit kdykoliv před tím a pak mu ji jen předat
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
15
Vaše jistota na trhu IT
Výjimky kontrolované a
nekontrolované
►Hierarchie výjimek
►Pořadí výjimek v blocích catch
►Metody generující výjimky
►Metody třídy Throwable
►Zřetězené výjimky
►Převod kontrolovaných na nekontrolované
Charakteristika
► Výjimky, které jsou potomky třídy RuntimeException
nebo Error označujeme jako nekontrolované (unchecked),
protože překladač nekontroluje, zda je na ně program připraven
► Ostatní výjimky označujeme jako kontrolované (checked),
protože překladač kontroluje dodržení pravidel:
● Každá metoda, která může vyhodit kontrolovanou výjimku,
se musí k této skutečnosti veřejně přihlásit
● Každé použití metody, která může vyhodit kontrolovanou výjimku,
musí být buď uzavřeno v bloku try…catch,
nebo se volající metoda musí přihlásit k tomu,
že může také vyhodit danou kontrolovanou výjimku
► Nekontrolované výjimky ohlašují chyby v programu,
kontrolované výjimky očekávatelné situace,
na jejichž výskyt má být program připraven
a měl by na ně umět reagovat
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
17
Hierarchie výjimek
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
18
Pořadí výjimek v blocích catch
► Třída NumberFormatException
je potomkem třídy RuntimeException
try {
Syntaktická chyba,
......
na druhý blok catch nikdy nedojde
}
catch (RuntimeException e) {
.........
}
Obrácené pořadí bloků catch
catch (NumberFormatException e){
vše vyřeší
........
try {
}
......
}
catch (NumberFormatException e) {
.........
}
catch (RuntimeException e){
........
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
19
Metody generující výjimky
► Java vyžaduje, aby programy, které používají metody
schopné vyvolat kontrolované výjimky,
byly o této schopnosti používaných metod informovány =>
pak vědí, které výjimku musí umět zachytit a ošetřit
► Všechny kontrolované výjimky, které může metoda vyhodit,
musí deklarovat v hlavičce za klíčovým slovem throws
► Deklarace vyhazování nekontrolovaných výjimek není povinná
public void metoda()
throws KontrolovanáVýjimka1,
KontrolovanáVýjimka2
{
// Tělo metody
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
20
Metody třídy Throwable
► String getMessage()
Vrátí zprávu popisující danou výjimku
► String toString()
Vrátí název třídy výjimky následovaný případnou zprávou
► void printStackTrace()
Vytiskne toString() následovaný sadou informací o volající
posloupnosti, která vedla k vzniku výjimky
► Throwable fillInStackTrace()
Připraví nové informace o volací posloupnosti
vedoucí k místu zavolání této metody
► StackTraceElement[] getStackTrace()
Vrátí uchované informace o volací posloupnosti dané výjimky
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
21
Zřetězené výjimky
► V některých situacích je vhodné v rámci ošetření výjimky vyvolat
jinou výjimku, a přitom umožnit zjistit,
která výjimka byla prvotním hybatelem celé akce
► Řada výjimek má mezi svými konstruktory i takové,
které akceptují jako poslední parametr
odkaz na výjimku, jež byla příčinou vyvolání dané výjimky
► Chce-li se program zeptat výjimky na výjimku, která ji způsobila,
použije metodu
public Throwable getCause()
► Ve zprávě o vyvolání výjimky jsou místa, kde byla jedna výjimka
nahrazena jinou, označována textem caused by:
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
22
Ukázka výpisu při zřetězení výjimek
HighLevelException: MidLevelException: LowLevelException
at Junk.a(Junk.java:13)
at Junk.main(Junk.java:4)
Caused by: MidLevelException: LowLevelException
at Junk.c(Junk.java:23)
at Junk.b(Junk.java:17)
at Junk.a(Junk.java:11)
... 1 more
Caused by: LowLevelException
at Junk.e(Junk.java:30)
at Junk.d(Junk.java:27)
at Junk.c(Junk.java:21)
... 3 more
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
23
Převod kontrolovaných na nekontrolované
► Ošetřování kontrolovaných výjimek obtěžuje
► Víme-li, že k dané výjimce nejspíš nedojde
a ošetřujeme-li ji pouze proto, že na tom překladač trvá,
můžeme pro případ, že by k výjimce přece jenom došlo
zaměnit kontrolovanou výjimku za nekontrolovanou
public void prevod( String s ) {
try {
prověř( s );
} catch( Exception ex ) {
throw new RuntimeException( " Neprověřeno! ", ex );
}
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
24
Vaše jistota na trhu IT
Definice vlastních výjimek
►Hierarchie výjimek
►Pořadí výjimek v blocích catch
►Metody generující výjimky
►Metody třídy Throwable
►Vlastní výjimky
►Zásady správného používání výjimek
Definice vlastních výjimek
► Výjimky jsou zcela běžné třídy;
považujeme-li to proto za vhodné, můžeme definovat i vlastní
► Před definicí nové výjimky bychom si měli ujasnit,
bude-li kontrolovaná či nekontrolovaná;
podle toho definujeme jejího předka
► Název výjimek končí dle konvencí slovem Exception
před nímž je naznačena podstata dané výjimky
● IllegalArgumetnException
● NoSuchMethodException
● BadStringOperationException
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
26
Příklad vlastní kontrolované výjimky
public class VelkýPrůšvihException
extends Exception
{
public VelkýPrůšvihException() {};
public VelkýPrůšvihException( String zpráva ) {
super( zpráva );
}
public VelkýPrůšvihException(String zpráva,
Throwable původce ) {
super( zpráva, původce );
}
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
27
Test správného vyhození výjimky
► Na vytvářených programech je třeba otestovat i to,
že v definovaných situacích vyhodí požadovanou výjimku
public void testVyhozeníVýjimky()
{
try {
metodaKteráMáVyhoditVýjimku();
} catch ( VelkýPrůšvihException vpe ) {
return;
}
fail( "Nebyla vyhozena výjimka VelkýPrůšvihException" );
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
28
Zásady správného používání výjimek
1/2
Neignorujte
výjimky
try {
//Nějaký kód
}
catch(Exception e){}
► Výjimky, o nichž víte, že nemohou nastat,
převeďte na nekontrolované pro případ,
že by v budoucích verzích programu nastat mohly
► Při ošetřování výjimek, které nastat mohou,
ale nemají vliv na chod programu,
vložte do těla ošetření alespoň vysvětlující komentář
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
29
Zásady správného používání výjimek
2/2
► Používejte výjimky pouze k ošetření výjimečných stavů
► Kontrolované výjimky používejte u stavů, z nichž se lze zotavit,
jinak použijte výjimky nekontrolované
► Vyhýbejte se zbytečnému používání kontrolovaných výjimek
● Programátory ošetřování kontrolovaných výjimek obtěžuje
a mají pak tendenci je ošetřovat prázdným blokem catch
► Dávejte přednost standardním výjimkám,
vyvolávejte výjimky odpovídající dané abstrakci
● Programátoři by měli z názvu výjimky poznat, co se stalo
● Standardní výjimky mají všeobecně známý význam
► Snažte se o atomičnost selhání; i po vyhození výjimky
by měl být objekt v dobře definovaném stavu
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
30
Zásady správného používání výjimek
3/2
► Doplňujte výjimky zprávami,
výjimka by sama měla poskytnout dostatek informací
a neměla by programátora nutit k podrobnější analýze programu
► Dokumentujte vyvolávané výjimky v dokumentačních
komentářích pomocí značky @throws
► Nedělejte bloky try zbytečně velké,
kód uvnitř těchto bloků se neoptimalizuje
► Umíte-li výjimku v metodě ošetřit, udělejte to
► Detekuje-li se chyba v jedné metodě a má se ošetřit v jiné
(stejné či jiné instance), použijte výjimku.
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
31
Nejčastěji používané výjimky
1/2
► IllegalArgumentException
Byla zadána nepovolená hodnota parametru
● Např. chci nastavit zápornou velikost grafického tvaru
► IllegalStateException
V daném stavu objektu nelze metodu provést
● Např. otevřu soubor, přečtu pár vět, zavřu soubor a chci znovu přečíst větu
► NullPointerException
Byla vyvolána metoda instance, na níž ukazuje prázdný odkaz,
nebo byl předán nepovolený prázdný odkaz v parametru
► ArrayIndexOutOfBoundException
Byly zadány špatné meze pole, buď záporné nebo moc velké
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
32
Nejčastěji používané výjimky
2/2
► ConcurrentModificationException
V průběhu iterace byla změněna struktura kontejneru
● Např. byl do kontejneru přidán prvek
► NumberFormatException
Je požadován špatný převod řetězce na číslo či naopak
● Chci-li např. převést na číslo řetězec, který není číslem
● Častá chyba v metodách String.format či PrintStream.printf
► ClassCastException
Požadované přetypování není možné
► UnsupportedOperationException
Požadovaná operace není podporována
(např. chci přidat prvek do neměnného kontejneru)
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
33
Vaše jistota na trhu IT
Děkuji za pozornost
►Rudolf Pecinovský
http://vyuka.pecinovsky.cz/vse
mail: [email protected]
ICQ: 158 156 600
Slide 5
Vaše jistota na trhu IT
Výjimky
Rudolf Pecinovský
[email protected]
Vaše jistota na trhu IT
Obsah s odkazy
►Výjimky
►Výjimky kontrolované a nekontrolované
►Definice vlastních výjimek
Vaše jistota na trhu IT
Výjimky
►Výjimečné situace v programech
►Ošetření nestandardních situací v Javě
►Zpráva o výjimce
►Klíčová slova
►Činnost
►Vyvolání
Výjimečné situace v programech
► V každém programu je alespoň jedna chyba –
program na ni musí být připraven
► Starší programy
● Program vypsal chybové hlášení a ukončil činnost;
● V některých situacích (válcovací stolice, autopilot, …) nepřijatelné
● Funkce vrátí hodnotu signalizující chybu
● Programátor musí neustále testovat, co funkce vrací
● Knihovna měla pro tyto účely vyhrazenu speciální proměnnou,
do níž se v případě chyby zapsal její kód; nahlédnutím do proměnné
program zjistil kód poslední chyby
● Programátor musí neustále testovat, jaká je v proměnné hodnota
► Některé jazyky (Cobol, PL/1, …) proto přišly s koncepcí
ošetření nestandardních situací
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
4
Ošetření nestandardních situací v Javě
► Výjimečná událost =
problém, který brání dalšímu vykonávání části kódu
► Událost je výjimečná v tom, že na rozdíl od běžných problémů
nemá program k vyřešení situace dost informaci
► Program může při výskytu výjimečné události vyvolat výjimku
► Výjimka (exception)
objekt určený k přenosu informací o nastalém problému
z místa jeho vzniku do místa, kde bude problém řešen
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
5
Postup při vyvolání výjimky
1. Vytvoří se výjimka = objekt typu Throwable
(prakticky vždy instance některého z potomků)
2. Vytvořená výjimka se vyhodí =
přeruší se běh programu v místě, kde výjimka vznikla,
a začne se hledat místo, kde bude daná výjimka ošetřena
3. Ošetření výjimky (handler) by mělo uvést program do stavu,
v němž může jeho vykonávání pokračovat
► Výjimka „probublává“ programem z místa vyhození stále výše
a nenarazí-li cestou nikde na své ošetření,
zachytí ji virtuální stroj, který na standardní chybový výstup
vypíše zprávu o vzniku výjimky
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
6
Systémová zpráva o vzniku výjimky
Zpráva o vzniku výjimky spolu s názvem vlákna,
v němž k výjimce došlo (zde AWT-EventQueue-0)
Popis druhu výjimky (aritmetická výjimka dělení nulou)
Informace o místě, odkud byla volána metoda,
která vyvolala metodu, v níž došlo k vyhození výjimky
Informace o místě, odkud byla volána metoda,
v níž došlo k vyhození výjimky
Úplný název třídy včetně balíčku
Copyright © 2006, Rudolf Pecinovský
Název metody
VŠE – 05
Název souboru se
zdrojovým kódem
Číslo řádku zdrojáku,
kde došlo k výjimce
7
Klíčová slova související s výjimkami
► try (zkus)
Označuje blok kódu, v němž může dojít k výjimce
► throw (hoď)
Příkaz k vyhození výjimky;
musí být následován odkazem na existující instanci
► catch (chyť)
Blok ošetřující výjimku, která je zadána jako parametr
► finally (na konec)
Blok s povinnými závěrečnými akcemi nezávisejícími
na případném vzniku výjimky
► throws (hází)
Uvození seznamu výjimek vyhazovaných danou metodou
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
8
Vyvolání a ošetření výjimky v kódu
try {
//Kód, který může vyvolat výjimky
}
catch( Typ1 id1 ) {
//Ošetření výjimek typu Typ1
}
...
catch( TypN idN ) {
//ošetření výjimek typu TypN
}
finally {
//Kód, který se na závěr VŽDY provede
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
9
Náznak činnosti – řádný průběh
nedojde k vyvolání výjimky
= nedojde k chybě
try {
příkaz1();
příkaz2();
příkaz3();
}
catch ( xxxException e ) {
příkazProOšetřeníChyby();
}
Bloky catch
catch (…..
se přeskočí
finally {
ukončovacíPříkazy();
}
dalšíPříkaz();
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
12
Náznak činnosti – ošetřený výjimka
try {
příkaz1(); Při provádění metody příkaz2
dojde k ošetřené chybě
příkaz2();
příkaz3();
Byla vyhozena výjimka
tohoto typu nebo typu
}
některého z potomků
catch ( xxxException e ) {
příkazProOšetřeníChyby();
}
Ostatní bloky catch
catch (…..
se přeskočí
finally {
ukončovacíPříkazy();
}
dalšíPříkaz();
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
13
Náznak činnosti – neošetřená výjimka
Při provádění metody příkaz2
dojde k NEošetřené chybě
try {
příkaz1();
příkaz2();
příkaz3();
}
catch ( xxxException e ) {
příkazProOšetřeníChyby();
}
Ošetření nebylo nalezeno =>
catch (…..
provede se blok finally
a opouští se metoda
finally {
ukončovacíPříkazy();
}
dalšíPříkaz();
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
14
Vyvolání výjimky
public class Xyz implements Comparable
{
public bolean compareTo( Object o )
{
if( !(o instanceOf Xyz) )
throw new ClassCastException (
"\nPokus o porovnání s neporovnatelnou"
+ " instancí " + o );
//Zjištění, kdo je větší
return vysledek;
}
}
► Instanci nemusíme vytvářet až v příkazu throw,
můžeme ji vytvořit kdykoliv před tím a pak mu ji jen předat
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
15
Vaše jistota na trhu IT
Výjimky kontrolované a
nekontrolované
►Hierarchie výjimek
►Pořadí výjimek v blocích catch
►Metody generující výjimky
►Metody třídy Throwable
►Zřetězené výjimky
►Převod kontrolovaných na nekontrolované
Charakteristika
► Výjimky, které jsou potomky třídy RuntimeException
nebo Error označujeme jako nekontrolované (unchecked),
protože překladač nekontroluje, zda je na ně program připraven
► Ostatní výjimky označujeme jako kontrolované (checked),
protože překladač kontroluje dodržení pravidel:
● Každá metoda, která může vyhodit kontrolovanou výjimku,
se musí k této skutečnosti veřejně přihlásit
● Každé použití metody, která může vyhodit kontrolovanou výjimku,
musí být buď uzavřeno v bloku try…catch,
nebo se volající metoda musí přihlásit k tomu,
že může také vyhodit danou kontrolovanou výjimku
► Nekontrolované výjimky ohlašují chyby v programu,
kontrolované výjimky očekávatelné situace,
na jejichž výskyt má být program připraven
a měl by na ně umět reagovat
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
17
Hierarchie výjimek
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
18
Pořadí výjimek v blocích catch
► Třída NumberFormatException
je potomkem třídy RuntimeException
try {
Syntaktická chyba,
......
na druhý blok catch nikdy nedojde
}
catch (RuntimeException e) {
.........
}
Obrácené pořadí bloků catch
catch (NumberFormatException e){
vše vyřeší
........
try {
}
......
}
catch (NumberFormatException e) {
.........
}
catch (RuntimeException e){
........
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
19
Metody generující výjimky
► Java vyžaduje, aby programy, které používají metody
schopné vyvolat kontrolované výjimky,
byly o této schopnosti používaných metod informovány =>
pak vědí, které výjimku musí umět zachytit a ošetřit
► Všechny kontrolované výjimky, které může metoda vyhodit,
musí deklarovat v hlavičce za klíčovým slovem throws
► Deklarace vyhazování nekontrolovaných výjimek není povinná
public void metoda()
throws KontrolovanáVýjimka1,
KontrolovanáVýjimka2
{
// Tělo metody
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
20
Metody třídy Throwable
► String getMessage()
Vrátí zprávu popisující danou výjimku
► String toString()
Vrátí název třídy výjimky následovaný případnou zprávou
► void printStackTrace()
Vytiskne toString() následovaný sadou informací o volající
posloupnosti, která vedla k vzniku výjimky
► Throwable fillInStackTrace()
Připraví nové informace o volací posloupnosti
vedoucí k místu zavolání této metody
► StackTraceElement[] getStackTrace()
Vrátí uchované informace o volací posloupnosti dané výjimky
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
21
Zřetězené výjimky
► V některých situacích je vhodné v rámci ošetření výjimky vyvolat
jinou výjimku, a přitom umožnit zjistit,
která výjimka byla prvotním hybatelem celé akce
► Řada výjimek má mezi svými konstruktory i takové,
které akceptují jako poslední parametr
odkaz na výjimku, jež byla příčinou vyvolání dané výjimky
► Chce-li se program zeptat výjimky na výjimku, která ji způsobila,
použije metodu
public Throwable getCause()
► Ve zprávě o vyvolání výjimky jsou místa, kde byla jedna výjimka
nahrazena jinou, označována textem caused by:
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
22
Ukázka výpisu při zřetězení výjimek
HighLevelException: MidLevelException: LowLevelException
at Junk.a(Junk.java:13)
at Junk.main(Junk.java:4)
Caused by: MidLevelException: LowLevelException
at Junk.c(Junk.java:23)
at Junk.b(Junk.java:17)
at Junk.a(Junk.java:11)
... 1 more
Caused by: LowLevelException
at Junk.e(Junk.java:30)
at Junk.d(Junk.java:27)
at Junk.c(Junk.java:21)
... 3 more
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
23
Převod kontrolovaných na nekontrolované
► Ošetřování kontrolovaných výjimek obtěžuje
► Víme-li, že k dané výjimce nejspíš nedojde
a ošetřujeme-li ji pouze proto, že na tom překladač trvá,
můžeme pro případ, že by k výjimce přece jenom došlo
zaměnit kontrolovanou výjimku za nekontrolovanou
public void prevod( String s ) {
try {
prověř( s );
} catch( Exception ex ) {
throw new RuntimeException( " Neprověřeno! ", ex );
}
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
24
Vaše jistota na trhu IT
Definice vlastních výjimek
►Hierarchie výjimek
►Pořadí výjimek v blocích catch
►Metody generující výjimky
►Metody třídy Throwable
►Vlastní výjimky
►Zásady správného používání výjimek
Definice vlastních výjimek
► Výjimky jsou zcela běžné třídy;
považujeme-li to proto za vhodné, můžeme definovat i vlastní
► Před definicí nové výjimky bychom si měli ujasnit,
bude-li kontrolovaná či nekontrolovaná;
podle toho definujeme jejího předka
► Název výjimek končí dle konvencí slovem Exception
před nímž je naznačena podstata dané výjimky
● IllegalArgumetnException
● NoSuchMethodException
● BadStringOperationException
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
26
Příklad vlastní kontrolované výjimky
public class VelkýPrůšvihException
extends Exception
{
public VelkýPrůšvihException() {};
public VelkýPrůšvihException( String zpráva ) {
super( zpráva );
}
public VelkýPrůšvihException(String zpráva,
Throwable původce ) {
super( zpráva, původce );
}
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
27
Test správného vyhození výjimky
► Na vytvářených programech je třeba otestovat i to,
že v definovaných situacích vyhodí požadovanou výjimku
public void testVyhozeníVýjimky()
{
try {
metodaKteráMáVyhoditVýjimku();
} catch ( VelkýPrůšvihException vpe ) {
return;
}
fail( "Nebyla vyhozena výjimka VelkýPrůšvihException" );
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
28
Zásady správného používání výjimek
1/2
Neignorujte
výjimky
try {
//Nějaký kód
}
catch(Exception e){}
► Výjimky, o nichž víte, že nemohou nastat,
převeďte na nekontrolované pro případ,
že by v budoucích verzích programu nastat mohly
► Při ošetřování výjimek, které nastat mohou,
ale nemají vliv na chod programu,
vložte do těla ošetření alespoň vysvětlující komentář
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
29
Zásady správného používání výjimek
2/2
► Používejte výjimky pouze k ošetření výjimečných stavů
► Kontrolované výjimky používejte u stavů, z nichž se lze zotavit,
jinak použijte výjimky nekontrolované
► Vyhýbejte se zbytečnému používání kontrolovaných výjimek
● Programátory ošetřování kontrolovaných výjimek obtěžuje
a mají pak tendenci je ošetřovat prázdným blokem catch
► Dávejte přednost standardním výjimkám,
vyvolávejte výjimky odpovídající dané abstrakci
● Programátoři by měli z názvu výjimky poznat, co se stalo
● Standardní výjimky mají všeobecně známý význam
► Snažte se o atomičnost selhání; i po vyhození výjimky
by měl být objekt v dobře definovaném stavu
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
30
Zásady správného používání výjimek
3/2
► Doplňujte výjimky zprávami,
výjimka by sama měla poskytnout dostatek informací
a neměla by programátora nutit k podrobnější analýze programu
► Dokumentujte vyvolávané výjimky v dokumentačních
komentářích pomocí značky @throws
► Nedělejte bloky try zbytečně velké,
kód uvnitř těchto bloků se neoptimalizuje
► Umíte-li výjimku v metodě ošetřit, udělejte to
► Detekuje-li se chyba v jedné metodě a má se ošetřit v jiné
(stejné či jiné instance), použijte výjimku.
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
31
Nejčastěji používané výjimky
1/2
► IllegalArgumentException
Byla zadána nepovolená hodnota parametru
● Např. chci nastavit zápornou velikost grafického tvaru
► IllegalStateException
V daném stavu objektu nelze metodu provést
● Např. otevřu soubor, přečtu pár vět, zavřu soubor a chci znovu přečíst větu
► NullPointerException
Byla vyvolána metoda instance, na níž ukazuje prázdný odkaz,
nebo byl předán nepovolený prázdný odkaz v parametru
► ArrayIndexOutOfBoundException
Byly zadány špatné meze pole, buď záporné nebo moc velké
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
32
Nejčastěji používané výjimky
2/2
► ConcurrentModificationException
V průběhu iterace byla změněna struktura kontejneru
● Např. byl do kontejneru přidán prvek
► NumberFormatException
Je požadován špatný převod řetězce na číslo či naopak
● Chci-li např. převést na číslo řetězec, který není číslem
● Častá chyba v metodách String.format či PrintStream.printf
► ClassCastException
Požadované přetypování není možné
► UnsupportedOperationException
Požadovaná operace není podporována
(např. chci přidat prvek do neměnného kontejneru)
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
33
Vaše jistota na trhu IT
Děkuji za pozornost
►Rudolf Pecinovský
http://vyuka.pecinovsky.cz/vse
mail: [email protected]
ICQ: 158 156 600
Slide 6
Vaše jistota na trhu IT
Výjimky
Rudolf Pecinovský
[email protected]
Vaše jistota na trhu IT
Obsah s odkazy
►Výjimky
►Výjimky kontrolované a nekontrolované
►Definice vlastních výjimek
Vaše jistota na trhu IT
Výjimky
►Výjimečné situace v programech
►Ošetření nestandardních situací v Javě
►Zpráva o výjimce
►Klíčová slova
►Činnost
►Vyvolání
Výjimečné situace v programech
► V každém programu je alespoň jedna chyba –
program na ni musí být připraven
► Starší programy
● Program vypsal chybové hlášení a ukončil činnost;
● V některých situacích (válcovací stolice, autopilot, …) nepřijatelné
● Funkce vrátí hodnotu signalizující chybu
● Programátor musí neustále testovat, co funkce vrací
● Knihovna měla pro tyto účely vyhrazenu speciální proměnnou,
do níž se v případě chyby zapsal její kód; nahlédnutím do proměnné
program zjistil kód poslední chyby
● Programátor musí neustále testovat, jaká je v proměnné hodnota
► Některé jazyky (Cobol, PL/1, …) proto přišly s koncepcí
ošetření nestandardních situací
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
4
Ošetření nestandardních situací v Javě
► Výjimečná událost =
problém, který brání dalšímu vykonávání části kódu
► Událost je výjimečná v tom, že na rozdíl od běžných problémů
nemá program k vyřešení situace dost informaci
► Program může při výskytu výjimečné události vyvolat výjimku
► Výjimka (exception)
objekt určený k přenosu informací o nastalém problému
z místa jeho vzniku do místa, kde bude problém řešen
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
5
Postup při vyvolání výjimky
1. Vytvoří se výjimka = objekt typu Throwable
(prakticky vždy instance některého z potomků)
2. Vytvořená výjimka se vyhodí =
přeruší se běh programu v místě, kde výjimka vznikla,
a začne se hledat místo, kde bude daná výjimka ošetřena
3. Ošetření výjimky (handler) by mělo uvést program do stavu,
v němž může jeho vykonávání pokračovat
► Výjimka „probublává“ programem z místa vyhození stále výše
a nenarazí-li cestou nikde na své ošetření,
zachytí ji virtuální stroj, který na standardní chybový výstup
vypíše zprávu o vzniku výjimky
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
6
Systémová zpráva o vzniku výjimky
Zpráva o vzniku výjimky spolu s názvem vlákna,
v němž k výjimce došlo (zde AWT-EventQueue-0)
Popis druhu výjimky (aritmetická výjimka dělení nulou)
Informace o místě, odkud byla volána metoda,
která vyvolala metodu, v níž došlo k vyhození výjimky
Informace o místě, odkud byla volána metoda,
v níž došlo k vyhození výjimky
Úplný název třídy včetně balíčku
Copyright © 2006, Rudolf Pecinovský
Název metody
VŠE – 05
Název souboru se
zdrojovým kódem
Číslo řádku zdrojáku,
kde došlo k výjimce
7
Klíčová slova související s výjimkami
► try (zkus)
Označuje blok kódu, v němž může dojít k výjimce
► throw (hoď)
Příkaz k vyhození výjimky;
musí být následován odkazem na existující instanci
► catch (chyť)
Blok ošetřující výjimku, která je zadána jako parametr
► finally (na konec)
Blok s povinnými závěrečnými akcemi nezávisejícími
na případném vzniku výjimky
► throws (hází)
Uvození seznamu výjimek vyhazovaných danou metodou
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
8
Vyvolání a ošetření výjimky v kódu
try {
//Kód, který může vyvolat výjimky
}
catch( Typ1 id1 ) {
//Ošetření výjimek typu Typ1
}
...
catch( TypN idN ) {
//ošetření výjimek typu TypN
}
finally {
//Kód, který se na závěr VŽDY provede
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
9
Náznak činnosti – řádný průběh
nedojde k vyvolání výjimky
= nedojde k chybě
try {
příkaz1();
příkaz2();
příkaz3();
}
catch ( xxxException e ) {
příkazProOšetřeníChyby();
}
Bloky catch
catch (…..
se přeskočí
finally {
ukončovacíPříkazy();
}
dalšíPříkaz();
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
12
Náznak činnosti – ošetřený výjimka
try {
příkaz1(); Při provádění metody příkaz2
dojde k ošetřené chybě
příkaz2();
příkaz3();
Byla vyhozena výjimka
tohoto typu nebo typu
}
některého z potomků
catch ( xxxException e ) {
příkazProOšetřeníChyby();
}
Ostatní bloky catch
catch (…..
se přeskočí
finally {
ukončovacíPříkazy();
}
dalšíPříkaz();
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
13
Náznak činnosti – neošetřená výjimka
Při provádění metody příkaz2
dojde k NEošetřené chybě
try {
příkaz1();
příkaz2();
příkaz3();
}
catch ( xxxException e ) {
příkazProOšetřeníChyby();
}
Ošetření nebylo nalezeno =>
catch (…..
provede se blok finally
a opouští se metoda
finally {
ukončovacíPříkazy();
}
dalšíPříkaz();
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
14
Vyvolání výjimky
public class Xyz implements Comparable
{
public bolean compareTo( Object o )
{
if( !(o instanceOf Xyz) )
throw new ClassCastException (
"\nPokus o porovnání s neporovnatelnou"
+ " instancí " + o );
//Zjištění, kdo je větší
return vysledek;
}
}
► Instanci nemusíme vytvářet až v příkazu throw,
můžeme ji vytvořit kdykoliv před tím a pak mu ji jen předat
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
15
Vaše jistota na trhu IT
Výjimky kontrolované a
nekontrolované
►Hierarchie výjimek
►Pořadí výjimek v blocích catch
►Metody generující výjimky
►Metody třídy Throwable
►Zřetězené výjimky
►Převod kontrolovaných na nekontrolované
Charakteristika
► Výjimky, které jsou potomky třídy RuntimeException
nebo Error označujeme jako nekontrolované (unchecked),
protože překladač nekontroluje, zda je na ně program připraven
► Ostatní výjimky označujeme jako kontrolované (checked),
protože překladač kontroluje dodržení pravidel:
● Každá metoda, která může vyhodit kontrolovanou výjimku,
se musí k této skutečnosti veřejně přihlásit
● Každé použití metody, která může vyhodit kontrolovanou výjimku,
musí být buď uzavřeno v bloku try…catch,
nebo se volající metoda musí přihlásit k tomu,
že může také vyhodit danou kontrolovanou výjimku
► Nekontrolované výjimky ohlašují chyby v programu,
kontrolované výjimky očekávatelné situace,
na jejichž výskyt má být program připraven
a měl by na ně umět reagovat
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
17
Hierarchie výjimek
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
18
Pořadí výjimek v blocích catch
► Třída NumberFormatException
je potomkem třídy RuntimeException
try {
Syntaktická chyba,
......
na druhý blok catch nikdy nedojde
}
catch (RuntimeException e) {
.........
}
Obrácené pořadí bloků catch
catch (NumberFormatException e){
vše vyřeší
........
try {
}
......
}
catch (NumberFormatException e) {
.........
}
catch (RuntimeException e){
........
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
19
Metody generující výjimky
► Java vyžaduje, aby programy, které používají metody
schopné vyvolat kontrolované výjimky,
byly o této schopnosti používaných metod informovány =>
pak vědí, které výjimku musí umět zachytit a ošetřit
► Všechny kontrolované výjimky, které může metoda vyhodit,
musí deklarovat v hlavičce za klíčovým slovem throws
► Deklarace vyhazování nekontrolovaných výjimek není povinná
public void metoda()
throws KontrolovanáVýjimka1,
KontrolovanáVýjimka2
{
// Tělo metody
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
20
Metody třídy Throwable
► String getMessage()
Vrátí zprávu popisující danou výjimku
► String toString()
Vrátí název třídy výjimky následovaný případnou zprávou
► void printStackTrace()
Vytiskne toString() následovaný sadou informací o volající
posloupnosti, která vedla k vzniku výjimky
► Throwable fillInStackTrace()
Připraví nové informace o volací posloupnosti
vedoucí k místu zavolání této metody
► StackTraceElement[] getStackTrace()
Vrátí uchované informace o volací posloupnosti dané výjimky
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
21
Zřetězené výjimky
► V některých situacích je vhodné v rámci ošetření výjimky vyvolat
jinou výjimku, a přitom umožnit zjistit,
která výjimka byla prvotním hybatelem celé akce
► Řada výjimek má mezi svými konstruktory i takové,
které akceptují jako poslední parametr
odkaz na výjimku, jež byla příčinou vyvolání dané výjimky
► Chce-li se program zeptat výjimky na výjimku, která ji způsobila,
použije metodu
public Throwable getCause()
► Ve zprávě o vyvolání výjimky jsou místa, kde byla jedna výjimka
nahrazena jinou, označována textem caused by:
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
22
Ukázka výpisu při zřetězení výjimek
HighLevelException: MidLevelException: LowLevelException
at Junk.a(Junk.java:13)
at Junk.main(Junk.java:4)
Caused by: MidLevelException: LowLevelException
at Junk.c(Junk.java:23)
at Junk.b(Junk.java:17)
at Junk.a(Junk.java:11)
... 1 more
Caused by: LowLevelException
at Junk.e(Junk.java:30)
at Junk.d(Junk.java:27)
at Junk.c(Junk.java:21)
... 3 more
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
23
Převod kontrolovaných na nekontrolované
► Ošetřování kontrolovaných výjimek obtěžuje
► Víme-li, že k dané výjimce nejspíš nedojde
a ošetřujeme-li ji pouze proto, že na tom překladač trvá,
můžeme pro případ, že by k výjimce přece jenom došlo
zaměnit kontrolovanou výjimku za nekontrolovanou
public void prevod( String s ) {
try {
prověř( s );
} catch( Exception ex ) {
throw new RuntimeException( " Neprověřeno! ", ex );
}
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
24
Vaše jistota na trhu IT
Definice vlastních výjimek
►Hierarchie výjimek
►Pořadí výjimek v blocích catch
►Metody generující výjimky
►Metody třídy Throwable
►Vlastní výjimky
►Zásady správného používání výjimek
Definice vlastních výjimek
► Výjimky jsou zcela běžné třídy;
považujeme-li to proto za vhodné, můžeme definovat i vlastní
► Před definicí nové výjimky bychom si měli ujasnit,
bude-li kontrolovaná či nekontrolovaná;
podle toho definujeme jejího předka
► Název výjimek končí dle konvencí slovem Exception
před nímž je naznačena podstata dané výjimky
● IllegalArgumetnException
● NoSuchMethodException
● BadStringOperationException
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
26
Příklad vlastní kontrolované výjimky
public class VelkýPrůšvihException
extends Exception
{
public VelkýPrůšvihException() {};
public VelkýPrůšvihException( String zpráva ) {
super( zpráva );
}
public VelkýPrůšvihException(String zpráva,
Throwable původce ) {
super( zpráva, původce );
}
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
27
Test správného vyhození výjimky
► Na vytvářených programech je třeba otestovat i to,
že v definovaných situacích vyhodí požadovanou výjimku
public void testVyhozeníVýjimky()
{
try {
metodaKteráMáVyhoditVýjimku();
} catch ( VelkýPrůšvihException vpe ) {
return;
}
fail( "Nebyla vyhozena výjimka VelkýPrůšvihException" );
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
28
Zásady správného používání výjimek
1/2
Neignorujte
výjimky
try {
//Nějaký kód
}
catch(Exception e){}
► Výjimky, o nichž víte, že nemohou nastat,
převeďte na nekontrolované pro případ,
že by v budoucích verzích programu nastat mohly
► Při ošetřování výjimek, které nastat mohou,
ale nemají vliv na chod programu,
vložte do těla ošetření alespoň vysvětlující komentář
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
29
Zásady správného používání výjimek
2/2
► Používejte výjimky pouze k ošetření výjimečných stavů
► Kontrolované výjimky používejte u stavů, z nichž se lze zotavit,
jinak použijte výjimky nekontrolované
► Vyhýbejte se zbytečnému používání kontrolovaných výjimek
● Programátory ošetřování kontrolovaných výjimek obtěžuje
a mají pak tendenci je ošetřovat prázdným blokem catch
► Dávejte přednost standardním výjimkám,
vyvolávejte výjimky odpovídající dané abstrakci
● Programátoři by měli z názvu výjimky poznat, co se stalo
● Standardní výjimky mají všeobecně známý význam
► Snažte se o atomičnost selhání; i po vyhození výjimky
by měl být objekt v dobře definovaném stavu
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
30
Zásady správného používání výjimek
3/2
► Doplňujte výjimky zprávami,
výjimka by sama měla poskytnout dostatek informací
a neměla by programátora nutit k podrobnější analýze programu
► Dokumentujte vyvolávané výjimky v dokumentačních
komentářích pomocí značky @throws
► Nedělejte bloky try zbytečně velké,
kód uvnitř těchto bloků se neoptimalizuje
► Umíte-li výjimku v metodě ošetřit, udělejte to
► Detekuje-li se chyba v jedné metodě a má se ošetřit v jiné
(stejné či jiné instance), použijte výjimku.
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
31
Nejčastěji používané výjimky
1/2
► IllegalArgumentException
Byla zadána nepovolená hodnota parametru
● Např. chci nastavit zápornou velikost grafického tvaru
► IllegalStateException
V daném stavu objektu nelze metodu provést
● Např. otevřu soubor, přečtu pár vět, zavřu soubor a chci znovu přečíst větu
► NullPointerException
Byla vyvolána metoda instance, na níž ukazuje prázdný odkaz,
nebo byl předán nepovolený prázdný odkaz v parametru
► ArrayIndexOutOfBoundException
Byly zadány špatné meze pole, buď záporné nebo moc velké
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
32
Nejčastěji používané výjimky
2/2
► ConcurrentModificationException
V průběhu iterace byla změněna struktura kontejneru
● Např. byl do kontejneru přidán prvek
► NumberFormatException
Je požadován špatný převod řetězce na číslo či naopak
● Chci-li např. převést na číslo řetězec, který není číslem
● Častá chyba v metodách String.format či PrintStream.printf
► ClassCastException
Požadované přetypování není možné
► UnsupportedOperationException
Požadovaná operace není podporována
(např. chci přidat prvek do neměnného kontejneru)
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
33
Vaše jistota na trhu IT
Děkuji za pozornost
►Rudolf Pecinovský
http://vyuka.pecinovsky.cz/vse
mail: [email protected]
ICQ: 158 156 600
Slide 7
Vaše jistota na trhu IT
Výjimky
Rudolf Pecinovský
[email protected]
Vaše jistota na trhu IT
Obsah s odkazy
►Výjimky
►Výjimky kontrolované a nekontrolované
►Definice vlastních výjimek
Vaše jistota na trhu IT
Výjimky
►Výjimečné situace v programech
►Ošetření nestandardních situací v Javě
►Zpráva o výjimce
►Klíčová slova
►Činnost
►Vyvolání
Výjimečné situace v programech
► V každém programu je alespoň jedna chyba –
program na ni musí být připraven
► Starší programy
● Program vypsal chybové hlášení a ukončil činnost;
● V některých situacích (válcovací stolice, autopilot, …) nepřijatelné
● Funkce vrátí hodnotu signalizující chybu
● Programátor musí neustále testovat, co funkce vrací
● Knihovna měla pro tyto účely vyhrazenu speciální proměnnou,
do níž se v případě chyby zapsal její kód; nahlédnutím do proměnné
program zjistil kód poslední chyby
● Programátor musí neustále testovat, jaká je v proměnné hodnota
► Některé jazyky (Cobol, PL/1, …) proto přišly s koncepcí
ošetření nestandardních situací
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
4
Ošetření nestandardních situací v Javě
► Výjimečná událost =
problém, který brání dalšímu vykonávání části kódu
► Událost je výjimečná v tom, že na rozdíl od běžných problémů
nemá program k vyřešení situace dost informaci
► Program může při výskytu výjimečné události vyvolat výjimku
► Výjimka (exception)
objekt určený k přenosu informací o nastalém problému
z místa jeho vzniku do místa, kde bude problém řešen
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
5
Postup při vyvolání výjimky
1. Vytvoří se výjimka = objekt typu Throwable
(prakticky vždy instance některého z potomků)
2. Vytvořená výjimka se vyhodí =
přeruší se běh programu v místě, kde výjimka vznikla,
a začne se hledat místo, kde bude daná výjimka ošetřena
3. Ošetření výjimky (handler) by mělo uvést program do stavu,
v němž může jeho vykonávání pokračovat
► Výjimka „probublává“ programem z místa vyhození stále výše
a nenarazí-li cestou nikde na své ošetření,
zachytí ji virtuální stroj, který na standardní chybový výstup
vypíše zprávu o vzniku výjimky
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
6
Systémová zpráva o vzniku výjimky
Zpráva o vzniku výjimky spolu s názvem vlákna,
v němž k výjimce došlo (zde AWT-EventQueue-0)
Popis druhu výjimky (aritmetická výjimka dělení nulou)
Informace o místě, odkud byla volána metoda,
která vyvolala metodu, v níž došlo k vyhození výjimky
Informace o místě, odkud byla volána metoda,
v níž došlo k vyhození výjimky
Úplný název třídy včetně balíčku
Copyright © 2006, Rudolf Pecinovský
Název metody
VŠE – 05
Název souboru se
zdrojovým kódem
Číslo řádku zdrojáku,
kde došlo k výjimce
7
Klíčová slova související s výjimkami
► try (zkus)
Označuje blok kódu, v němž může dojít k výjimce
► throw (hoď)
Příkaz k vyhození výjimky;
musí být následován odkazem na existující instanci
► catch (chyť)
Blok ošetřující výjimku, která je zadána jako parametr
► finally (na konec)
Blok s povinnými závěrečnými akcemi nezávisejícími
na případném vzniku výjimky
► throws (hází)
Uvození seznamu výjimek vyhazovaných danou metodou
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
8
Vyvolání a ošetření výjimky v kódu
try {
//Kód, který může vyvolat výjimky
}
catch( Typ1 id1 ) {
//Ošetření výjimek typu Typ1
}
...
catch( TypN idN ) {
//ošetření výjimek typu TypN
}
finally {
//Kód, který se na závěr VŽDY provede
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
9
Náznak činnosti – řádný průběh
nedojde k vyvolání výjimky
= nedojde k chybě
try {
příkaz1();
příkaz2();
příkaz3();
}
catch ( xxxException e ) {
příkazProOšetřeníChyby();
}
Bloky catch
catch (…..
se přeskočí
finally {
ukončovacíPříkazy();
}
dalšíPříkaz();
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
12
Náznak činnosti – ošetřený výjimka
try {
příkaz1(); Při provádění metody příkaz2
dojde k ošetřené chybě
příkaz2();
příkaz3();
Byla vyhozena výjimka
tohoto typu nebo typu
}
některého z potomků
catch ( xxxException e ) {
příkazProOšetřeníChyby();
}
Ostatní bloky catch
catch (…..
se přeskočí
finally {
ukončovacíPříkazy();
}
dalšíPříkaz();
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
13
Náznak činnosti – neošetřená výjimka
Při provádění metody příkaz2
dojde k NEošetřené chybě
try {
příkaz1();
příkaz2();
příkaz3();
}
catch ( xxxException e ) {
příkazProOšetřeníChyby();
}
Ošetření nebylo nalezeno =>
catch (…..
provede se blok finally
a opouští se metoda
finally {
ukončovacíPříkazy();
}
dalšíPříkaz();
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
14
Vyvolání výjimky
public class Xyz implements Comparable
{
public bolean compareTo( Object o )
{
if( !(o instanceOf Xyz) )
throw new ClassCastException (
"\nPokus o porovnání s neporovnatelnou"
+ " instancí " + o );
//Zjištění, kdo je větší
return vysledek;
}
}
► Instanci nemusíme vytvářet až v příkazu throw,
můžeme ji vytvořit kdykoliv před tím a pak mu ji jen předat
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
15
Vaše jistota na trhu IT
Výjimky kontrolované a
nekontrolované
►Hierarchie výjimek
►Pořadí výjimek v blocích catch
►Metody generující výjimky
►Metody třídy Throwable
►Zřetězené výjimky
►Převod kontrolovaných na nekontrolované
Charakteristika
► Výjimky, které jsou potomky třídy RuntimeException
nebo Error označujeme jako nekontrolované (unchecked),
protože překladač nekontroluje, zda je na ně program připraven
► Ostatní výjimky označujeme jako kontrolované (checked),
protože překladač kontroluje dodržení pravidel:
● Každá metoda, která může vyhodit kontrolovanou výjimku,
se musí k této skutečnosti veřejně přihlásit
● Každé použití metody, která může vyhodit kontrolovanou výjimku,
musí být buď uzavřeno v bloku try…catch,
nebo se volající metoda musí přihlásit k tomu,
že může také vyhodit danou kontrolovanou výjimku
► Nekontrolované výjimky ohlašují chyby v programu,
kontrolované výjimky očekávatelné situace,
na jejichž výskyt má být program připraven
a měl by na ně umět reagovat
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
17
Hierarchie výjimek
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
18
Pořadí výjimek v blocích catch
► Třída NumberFormatException
je potomkem třídy RuntimeException
try {
Syntaktická chyba,
......
na druhý blok catch nikdy nedojde
}
catch (RuntimeException e) {
.........
}
Obrácené pořadí bloků catch
catch (NumberFormatException e){
vše vyřeší
........
try {
}
......
}
catch (NumberFormatException e) {
.........
}
catch (RuntimeException e){
........
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
19
Metody generující výjimky
► Java vyžaduje, aby programy, které používají metody
schopné vyvolat kontrolované výjimky,
byly o této schopnosti používaných metod informovány =>
pak vědí, které výjimku musí umět zachytit a ošetřit
► Všechny kontrolované výjimky, které může metoda vyhodit,
musí deklarovat v hlavičce za klíčovým slovem throws
► Deklarace vyhazování nekontrolovaných výjimek není povinná
public void metoda()
throws KontrolovanáVýjimka1,
KontrolovanáVýjimka2
{
// Tělo metody
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
20
Metody třídy Throwable
► String getMessage()
Vrátí zprávu popisující danou výjimku
► String toString()
Vrátí název třídy výjimky následovaný případnou zprávou
► void printStackTrace()
Vytiskne toString() následovaný sadou informací o volající
posloupnosti, která vedla k vzniku výjimky
► Throwable fillInStackTrace()
Připraví nové informace o volací posloupnosti
vedoucí k místu zavolání této metody
► StackTraceElement[] getStackTrace()
Vrátí uchované informace o volací posloupnosti dané výjimky
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
21
Zřetězené výjimky
► V některých situacích je vhodné v rámci ošetření výjimky vyvolat
jinou výjimku, a přitom umožnit zjistit,
která výjimka byla prvotním hybatelem celé akce
► Řada výjimek má mezi svými konstruktory i takové,
které akceptují jako poslední parametr
odkaz na výjimku, jež byla příčinou vyvolání dané výjimky
► Chce-li se program zeptat výjimky na výjimku, která ji způsobila,
použije metodu
public Throwable getCause()
► Ve zprávě o vyvolání výjimky jsou místa, kde byla jedna výjimka
nahrazena jinou, označována textem caused by:
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
22
Ukázka výpisu při zřetězení výjimek
HighLevelException: MidLevelException: LowLevelException
at Junk.a(Junk.java:13)
at Junk.main(Junk.java:4)
Caused by: MidLevelException: LowLevelException
at Junk.c(Junk.java:23)
at Junk.b(Junk.java:17)
at Junk.a(Junk.java:11)
... 1 more
Caused by: LowLevelException
at Junk.e(Junk.java:30)
at Junk.d(Junk.java:27)
at Junk.c(Junk.java:21)
... 3 more
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
23
Převod kontrolovaných na nekontrolované
► Ošetřování kontrolovaných výjimek obtěžuje
► Víme-li, že k dané výjimce nejspíš nedojde
a ošetřujeme-li ji pouze proto, že na tom překladač trvá,
můžeme pro případ, že by k výjimce přece jenom došlo
zaměnit kontrolovanou výjimku za nekontrolovanou
public void prevod( String s ) {
try {
prověř( s );
} catch( Exception ex ) {
throw new RuntimeException( " Neprověřeno! ", ex );
}
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
24
Vaše jistota na trhu IT
Definice vlastních výjimek
►Hierarchie výjimek
►Pořadí výjimek v blocích catch
►Metody generující výjimky
►Metody třídy Throwable
►Vlastní výjimky
►Zásady správného používání výjimek
Definice vlastních výjimek
► Výjimky jsou zcela běžné třídy;
považujeme-li to proto za vhodné, můžeme definovat i vlastní
► Před definicí nové výjimky bychom si měli ujasnit,
bude-li kontrolovaná či nekontrolovaná;
podle toho definujeme jejího předka
► Název výjimek končí dle konvencí slovem Exception
před nímž je naznačena podstata dané výjimky
● IllegalArgumetnException
● NoSuchMethodException
● BadStringOperationException
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
26
Příklad vlastní kontrolované výjimky
public class VelkýPrůšvihException
extends Exception
{
public VelkýPrůšvihException() {};
public VelkýPrůšvihException( String zpráva ) {
super( zpráva );
}
public VelkýPrůšvihException(String zpráva,
Throwable původce ) {
super( zpráva, původce );
}
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
27
Test správného vyhození výjimky
► Na vytvářených programech je třeba otestovat i to,
že v definovaných situacích vyhodí požadovanou výjimku
public void testVyhozeníVýjimky()
{
try {
metodaKteráMáVyhoditVýjimku();
} catch ( VelkýPrůšvihException vpe ) {
return;
}
fail( "Nebyla vyhozena výjimka VelkýPrůšvihException" );
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
28
Zásady správného používání výjimek
1/2
Neignorujte
výjimky
try {
//Nějaký kód
}
catch(Exception e){}
► Výjimky, o nichž víte, že nemohou nastat,
převeďte na nekontrolované pro případ,
že by v budoucích verzích programu nastat mohly
► Při ošetřování výjimek, které nastat mohou,
ale nemají vliv na chod programu,
vložte do těla ošetření alespoň vysvětlující komentář
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
29
Zásady správného používání výjimek
2/2
► Používejte výjimky pouze k ošetření výjimečných stavů
► Kontrolované výjimky používejte u stavů, z nichž se lze zotavit,
jinak použijte výjimky nekontrolované
► Vyhýbejte se zbytečnému používání kontrolovaných výjimek
● Programátory ošetřování kontrolovaných výjimek obtěžuje
a mají pak tendenci je ošetřovat prázdným blokem catch
► Dávejte přednost standardním výjimkám,
vyvolávejte výjimky odpovídající dané abstrakci
● Programátoři by měli z názvu výjimky poznat, co se stalo
● Standardní výjimky mají všeobecně známý význam
► Snažte se o atomičnost selhání; i po vyhození výjimky
by měl být objekt v dobře definovaném stavu
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
30
Zásady správného používání výjimek
3/2
► Doplňujte výjimky zprávami,
výjimka by sama měla poskytnout dostatek informací
a neměla by programátora nutit k podrobnější analýze programu
► Dokumentujte vyvolávané výjimky v dokumentačních
komentářích pomocí značky @throws
► Nedělejte bloky try zbytečně velké,
kód uvnitř těchto bloků se neoptimalizuje
► Umíte-li výjimku v metodě ošetřit, udělejte to
► Detekuje-li se chyba v jedné metodě a má se ošetřit v jiné
(stejné či jiné instance), použijte výjimku.
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
31
Nejčastěji používané výjimky
1/2
► IllegalArgumentException
Byla zadána nepovolená hodnota parametru
● Např. chci nastavit zápornou velikost grafického tvaru
► IllegalStateException
V daném stavu objektu nelze metodu provést
● Např. otevřu soubor, přečtu pár vět, zavřu soubor a chci znovu přečíst větu
► NullPointerException
Byla vyvolána metoda instance, na níž ukazuje prázdný odkaz,
nebo byl předán nepovolený prázdný odkaz v parametru
► ArrayIndexOutOfBoundException
Byly zadány špatné meze pole, buď záporné nebo moc velké
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
32
Nejčastěji používané výjimky
2/2
► ConcurrentModificationException
V průběhu iterace byla změněna struktura kontejneru
● Např. byl do kontejneru přidán prvek
► NumberFormatException
Je požadován špatný převod řetězce na číslo či naopak
● Chci-li např. převést na číslo řetězec, který není číslem
● Častá chyba v metodách String.format či PrintStream.printf
► ClassCastException
Požadované přetypování není možné
► UnsupportedOperationException
Požadovaná operace není podporována
(např. chci přidat prvek do neměnného kontejneru)
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
33
Vaše jistota na trhu IT
Děkuji za pozornost
►Rudolf Pecinovský
http://vyuka.pecinovsky.cz/vse
mail: [email protected]
ICQ: 158 156 600
Slide 8
Vaše jistota na trhu IT
Výjimky
Rudolf Pecinovský
[email protected]
Vaše jistota na trhu IT
Obsah s odkazy
►Výjimky
►Výjimky kontrolované a nekontrolované
►Definice vlastních výjimek
Vaše jistota na trhu IT
Výjimky
►Výjimečné situace v programech
►Ošetření nestandardních situací v Javě
►Zpráva o výjimce
►Klíčová slova
►Činnost
►Vyvolání
Výjimečné situace v programech
► V každém programu je alespoň jedna chyba –
program na ni musí být připraven
► Starší programy
● Program vypsal chybové hlášení a ukončil činnost;
● V některých situacích (válcovací stolice, autopilot, …) nepřijatelné
● Funkce vrátí hodnotu signalizující chybu
● Programátor musí neustále testovat, co funkce vrací
● Knihovna měla pro tyto účely vyhrazenu speciální proměnnou,
do níž se v případě chyby zapsal její kód; nahlédnutím do proměnné
program zjistil kód poslední chyby
● Programátor musí neustále testovat, jaká je v proměnné hodnota
► Některé jazyky (Cobol, PL/1, …) proto přišly s koncepcí
ošetření nestandardních situací
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
4
Ošetření nestandardních situací v Javě
► Výjimečná událost =
problém, který brání dalšímu vykonávání části kódu
► Událost je výjimečná v tom, že na rozdíl od běžných problémů
nemá program k vyřešení situace dost informaci
► Program může při výskytu výjimečné události vyvolat výjimku
► Výjimka (exception)
objekt určený k přenosu informací o nastalém problému
z místa jeho vzniku do místa, kde bude problém řešen
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
5
Postup při vyvolání výjimky
1. Vytvoří se výjimka = objekt typu Throwable
(prakticky vždy instance některého z potomků)
2. Vytvořená výjimka se vyhodí =
přeruší se běh programu v místě, kde výjimka vznikla,
a začne se hledat místo, kde bude daná výjimka ošetřena
3. Ošetření výjimky (handler) by mělo uvést program do stavu,
v němž může jeho vykonávání pokračovat
► Výjimka „probublává“ programem z místa vyhození stále výše
a nenarazí-li cestou nikde na své ošetření,
zachytí ji virtuální stroj, který na standardní chybový výstup
vypíše zprávu o vzniku výjimky
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
6
Systémová zpráva o vzniku výjimky
Zpráva o vzniku výjimky spolu s názvem vlákna,
v němž k výjimce došlo (zde AWT-EventQueue-0)
Popis druhu výjimky (aritmetická výjimka dělení nulou)
Informace o místě, odkud byla volána metoda,
která vyvolala metodu, v níž došlo k vyhození výjimky
Informace o místě, odkud byla volána metoda,
v níž došlo k vyhození výjimky
Úplný název třídy včetně balíčku
Copyright © 2006, Rudolf Pecinovský
Název metody
VŠE – 05
Název souboru se
zdrojovým kódem
Číslo řádku zdrojáku,
kde došlo k výjimce
7
Klíčová slova související s výjimkami
► try (zkus)
Označuje blok kódu, v němž může dojít k výjimce
► throw (hoď)
Příkaz k vyhození výjimky;
musí být následován odkazem na existující instanci
► catch (chyť)
Blok ošetřující výjimku, která je zadána jako parametr
► finally (na konec)
Blok s povinnými závěrečnými akcemi nezávisejícími
na případném vzniku výjimky
► throws (hází)
Uvození seznamu výjimek vyhazovaných danou metodou
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
8
Vyvolání a ošetření výjimky v kódu
try {
//Kód, který může vyvolat výjimky
}
catch( Typ1 id1 ) {
//Ošetření výjimek typu Typ1
}
...
catch( TypN idN ) {
//ošetření výjimek typu TypN
}
finally {
//Kód, který se na závěr VŽDY provede
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
9
Náznak činnosti – řádný průběh
nedojde k vyvolání výjimky
= nedojde k chybě
try {
příkaz1();
příkaz2();
příkaz3();
}
catch ( xxxException e ) {
příkazProOšetřeníChyby();
}
Bloky catch
catch (…..
se přeskočí
finally {
ukončovacíPříkazy();
}
dalšíPříkaz();
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
12
Náznak činnosti – ošetřený výjimka
try {
příkaz1(); Při provádění metody příkaz2
dojde k ošetřené chybě
příkaz2();
příkaz3();
Byla vyhozena výjimka
tohoto typu nebo typu
}
některého z potomků
catch ( xxxException e ) {
příkazProOšetřeníChyby();
}
Ostatní bloky catch
catch (…..
se přeskočí
finally {
ukončovacíPříkazy();
}
dalšíPříkaz();
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
13
Náznak činnosti – neošetřená výjimka
Při provádění metody příkaz2
dojde k NEošetřené chybě
try {
příkaz1();
příkaz2();
příkaz3();
}
catch ( xxxException e ) {
příkazProOšetřeníChyby();
}
Ošetření nebylo nalezeno =>
catch (…..
provede se blok finally
a opouští se metoda
finally {
ukončovacíPříkazy();
}
dalšíPříkaz();
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
14
Vyvolání výjimky
public class Xyz implements Comparable
{
public bolean compareTo( Object o )
{
if( !(o instanceOf Xyz) )
throw new ClassCastException (
"\nPokus o porovnání s neporovnatelnou"
+ " instancí " + o );
//Zjištění, kdo je větší
return vysledek;
}
}
► Instanci nemusíme vytvářet až v příkazu throw,
můžeme ji vytvořit kdykoliv před tím a pak mu ji jen předat
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
15
Vaše jistota na trhu IT
Výjimky kontrolované a
nekontrolované
►Hierarchie výjimek
►Pořadí výjimek v blocích catch
►Metody generující výjimky
►Metody třídy Throwable
►Zřetězené výjimky
►Převod kontrolovaných na nekontrolované
Charakteristika
► Výjimky, které jsou potomky třídy RuntimeException
nebo Error označujeme jako nekontrolované (unchecked),
protože překladač nekontroluje, zda je na ně program připraven
► Ostatní výjimky označujeme jako kontrolované (checked),
protože překladač kontroluje dodržení pravidel:
● Každá metoda, která může vyhodit kontrolovanou výjimku,
se musí k této skutečnosti veřejně přihlásit
● Každé použití metody, která může vyhodit kontrolovanou výjimku,
musí být buď uzavřeno v bloku try…catch,
nebo se volající metoda musí přihlásit k tomu,
že může také vyhodit danou kontrolovanou výjimku
► Nekontrolované výjimky ohlašují chyby v programu,
kontrolované výjimky očekávatelné situace,
na jejichž výskyt má být program připraven
a měl by na ně umět reagovat
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
17
Hierarchie výjimek
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
18
Pořadí výjimek v blocích catch
► Třída NumberFormatException
je potomkem třídy RuntimeException
try {
Syntaktická chyba,
......
na druhý blok catch nikdy nedojde
}
catch (RuntimeException e) {
.........
}
Obrácené pořadí bloků catch
catch (NumberFormatException e){
vše vyřeší
........
try {
}
......
}
catch (NumberFormatException e) {
.........
}
catch (RuntimeException e){
........
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
19
Metody generující výjimky
► Java vyžaduje, aby programy, které používají metody
schopné vyvolat kontrolované výjimky,
byly o této schopnosti používaných metod informovány =>
pak vědí, které výjimku musí umět zachytit a ošetřit
► Všechny kontrolované výjimky, které může metoda vyhodit,
musí deklarovat v hlavičce za klíčovým slovem throws
► Deklarace vyhazování nekontrolovaných výjimek není povinná
public void metoda()
throws KontrolovanáVýjimka1,
KontrolovanáVýjimka2
{
// Tělo metody
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
20
Metody třídy Throwable
► String getMessage()
Vrátí zprávu popisující danou výjimku
► String toString()
Vrátí název třídy výjimky následovaný případnou zprávou
► void printStackTrace()
Vytiskne toString() následovaný sadou informací o volající
posloupnosti, která vedla k vzniku výjimky
► Throwable fillInStackTrace()
Připraví nové informace o volací posloupnosti
vedoucí k místu zavolání této metody
► StackTraceElement[] getStackTrace()
Vrátí uchované informace o volací posloupnosti dané výjimky
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
21
Zřetězené výjimky
► V některých situacích je vhodné v rámci ošetření výjimky vyvolat
jinou výjimku, a přitom umožnit zjistit,
která výjimka byla prvotním hybatelem celé akce
► Řada výjimek má mezi svými konstruktory i takové,
které akceptují jako poslední parametr
odkaz na výjimku, jež byla příčinou vyvolání dané výjimky
► Chce-li se program zeptat výjimky na výjimku, která ji způsobila,
použije metodu
public Throwable getCause()
► Ve zprávě o vyvolání výjimky jsou místa, kde byla jedna výjimka
nahrazena jinou, označována textem caused by:
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
22
Ukázka výpisu při zřetězení výjimek
HighLevelException: MidLevelException: LowLevelException
at Junk.a(Junk.java:13)
at Junk.main(Junk.java:4)
Caused by: MidLevelException: LowLevelException
at Junk.c(Junk.java:23)
at Junk.b(Junk.java:17)
at Junk.a(Junk.java:11)
... 1 more
Caused by: LowLevelException
at Junk.e(Junk.java:30)
at Junk.d(Junk.java:27)
at Junk.c(Junk.java:21)
... 3 more
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
23
Převod kontrolovaných na nekontrolované
► Ošetřování kontrolovaných výjimek obtěžuje
► Víme-li, že k dané výjimce nejspíš nedojde
a ošetřujeme-li ji pouze proto, že na tom překladač trvá,
můžeme pro případ, že by k výjimce přece jenom došlo
zaměnit kontrolovanou výjimku za nekontrolovanou
public void prevod( String s ) {
try {
prověř( s );
} catch( Exception ex ) {
throw new RuntimeException( " Neprověřeno! ", ex );
}
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
24
Vaše jistota na trhu IT
Definice vlastních výjimek
►Hierarchie výjimek
►Pořadí výjimek v blocích catch
►Metody generující výjimky
►Metody třídy Throwable
►Vlastní výjimky
►Zásady správného používání výjimek
Definice vlastních výjimek
► Výjimky jsou zcela běžné třídy;
považujeme-li to proto za vhodné, můžeme definovat i vlastní
► Před definicí nové výjimky bychom si měli ujasnit,
bude-li kontrolovaná či nekontrolovaná;
podle toho definujeme jejího předka
► Název výjimek končí dle konvencí slovem Exception
před nímž je naznačena podstata dané výjimky
● IllegalArgumetnException
● NoSuchMethodException
● BadStringOperationException
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
26
Příklad vlastní kontrolované výjimky
public class VelkýPrůšvihException
extends Exception
{
public VelkýPrůšvihException() {};
public VelkýPrůšvihException( String zpráva ) {
super( zpráva );
}
public VelkýPrůšvihException(String zpráva,
Throwable původce ) {
super( zpráva, původce );
}
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
27
Test správného vyhození výjimky
► Na vytvářených programech je třeba otestovat i to,
že v definovaných situacích vyhodí požadovanou výjimku
public void testVyhozeníVýjimky()
{
try {
metodaKteráMáVyhoditVýjimku();
} catch ( VelkýPrůšvihException vpe ) {
return;
}
fail( "Nebyla vyhozena výjimka VelkýPrůšvihException" );
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
28
Zásady správného používání výjimek
1/2
Neignorujte
výjimky
try {
//Nějaký kód
}
catch(Exception e){}
► Výjimky, o nichž víte, že nemohou nastat,
převeďte na nekontrolované pro případ,
že by v budoucích verzích programu nastat mohly
► Při ošetřování výjimek, které nastat mohou,
ale nemají vliv na chod programu,
vložte do těla ošetření alespoň vysvětlující komentář
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
29
Zásady správného používání výjimek
2/2
► Používejte výjimky pouze k ošetření výjimečných stavů
► Kontrolované výjimky používejte u stavů, z nichž se lze zotavit,
jinak použijte výjimky nekontrolované
► Vyhýbejte se zbytečnému používání kontrolovaných výjimek
● Programátory ošetřování kontrolovaných výjimek obtěžuje
a mají pak tendenci je ošetřovat prázdným blokem catch
► Dávejte přednost standardním výjimkám,
vyvolávejte výjimky odpovídající dané abstrakci
● Programátoři by měli z názvu výjimky poznat, co se stalo
● Standardní výjimky mají všeobecně známý význam
► Snažte se o atomičnost selhání; i po vyhození výjimky
by měl být objekt v dobře definovaném stavu
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
30
Zásady správného používání výjimek
3/2
► Doplňujte výjimky zprávami,
výjimka by sama měla poskytnout dostatek informací
a neměla by programátora nutit k podrobnější analýze programu
► Dokumentujte vyvolávané výjimky v dokumentačních
komentářích pomocí značky @throws
► Nedělejte bloky try zbytečně velké,
kód uvnitř těchto bloků se neoptimalizuje
► Umíte-li výjimku v metodě ošetřit, udělejte to
► Detekuje-li se chyba v jedné metodě a má se ošetřit v jiné
(stejné či jiné instance), použijte výjimku.
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
31
Nejčastěji používané výjimky
1/2
► IllegalArgumentException
Byla zadána nepovolená hodnota parametru
● Např. chci nastavit zápornou velikost grafického tvaru
► IllegalStateException
V daném stavu objektu nelze metodu provést
● Např. otevřu soubor, přečtu pár vět, zavřu soubor a chci znovu přečíst větu
► NullPointerException
Byla vyvolána metoda instance, na níž ukazuje prázdný odkaz,
nebo byl předán nepovolený prázdný odkaz v parametru
► ArrayIndexOutOfBoundException
Byly zadány špatné meze pole, buď záporné nebo moc velké
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
32
Nejčastěji používané výjimky
2/2
► ConcurrentModificationException
V průběhu iterace byla změněna struktura kontejneru
● Např. byl do kontejneru přidán prvek
► NumberFormatException
Je požadován špatný převod řetězce na číslo či naopak
● Chci-li např. převést na číslo řetězec, který není číslem
● Častá chyba v metodách String.format či PrintStream.printf
► ClassCastException
Požadované přetypování není možné
► UnsupportedOperationException
Požadovaná operace není podporována
(např. chci přidat prvek do neměnného kontejneru)
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
33
Vaše jistota na trhu IT
Děkuji za pozornost
►Rudolf Pecinovský
http://vyuka.pecinovsky.cz/vse
mail: [email protected]
ICQ: 158 156 600
Slide 9
Vaše jistota na trhu IT
Výjimky
Rudolf Pecinovský
[email protected]
Vaše jistota na trhu IT
Obsah s odkazy
►Výjimky
►Výjimky kontrolované a nekontrolované
►Definice vlastních výjimek
Vaše jistota na trhu IT
Výjimky
►Výjimečné situace v programech
►Ošetření nestandardních situací v Javě
►Zpráva o výjimce
►Klíčová slova
►Činnost
►Vyvolání
Výjimečné situace v programech
► V každém programu je alespoň jedna chyba –
program na ni musí být připraven
► Starší programy
● Program vypsal chybové hlášení a ukončil činnost;
● V některých situacích (válcovací stolice, autopilot, …) nepřijatelné
● Funkce vrátí hodnotu signalizující chybu
● Programátor musí neustále testovat, co funkce vrací
● Knihovna měla pro tyto účely vyhrazenu speciální proměnnou,
do níž se v případě chyby zapsal její kód; nahlédnutím do proměnné
program zjistil kód poslední chyby
● Programátor musí neustále testovat, jaká je v proměnné hodnota
► Některé jazyky (Cobol, PL/1, …) proto přišly s koncepcí
ošetření nestandardních situací
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
4
Ošetření nestandardních situací v Javě
► Výjimečná událost =
problém, který brání dalšímu vykonávání části kódu
► Událost je výjimečná v tom, že na rozdíl od běžných problémů
nemá program k vyřešení situace dost informaci
► Program může při výskytu výjimečné události vyvolat výjimku
► Výjimka (exception)
objekt určený k přenosu informací o nastalém problému
z místa jeho vzniku do místa, kde bude problém řešen
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
5
Postup při vyvolání výjimky
1. Vytvoří se výjimka = objekt typu Throwable
(prakticky vždy instance některého z potomků)
2. Vytvořená výjimka se vyhodí =
přeruší se běh programu v místě, kde výjimka vznikla,
a začne se hledat místo, kde bude daná výjimka ošetřena
3. Ošetření výjimky (handler) by mělo uvést program do stavu,
v němž může jeho vykonávání pokračovat
► Výjimka „probublává“ programem z místa vyhození stále výše
a nenarazí-li cestou nikde na své ošetření,
zachytí ji virtuální stroj, který na standardní chybový výstup
vypíše zprávu o vzniku výjimky
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
6
Systémová zpráva o vzniku výjimky
Zpráva o vzniku výjimky spolu s názvem vlákna,
v němž k výjimce došlo (zde AWT-EventQueue-0)
Popis druhu výjimky (aritmetická výjimka dělení nulou)
Informace o místě, odkud byla volána metoda,
která vyvolala metodu, v níž došlo k vyhození výjimky
Informace o místě, odkud byla volána metoda,
v níž došlo k vyhození výjimky
Úplný název třídy včetně balíčku
Copyright © 2006, Rudolf Pecinovský
Název metody
VŠE – 05
Název souboru se
zdrojovým kódem
Číslo řádku zdrojáku,
kde došlo k výjimce
7
Klíčová slova související s výjimkami
► try (zkus)
Označuje blok kódu, v němž může dojít k výjimce
► throw (hoď)
Příkaz k vyhození výjimky;
musí být následován odkazem na existující instanci
► catch (chyť)
Blok ošetřující výjimku, která je zadána jako parametr
► finally (na konec)
Blok s povinnými závěrečnými akcemi nezávisejícími
na případném vzniku výjimky
► throws (hází)
Uvození seznamu výjimek vyhazovaných danou metodou
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
8
Vyvolání a ošetření výjimky v kódu
try {
//Kód, který může vyvolat výjimky
}
catch( Typ1 id1 ) {
//Ošetření výjimek typu Typ1
}
...
catch( TypN idN ) {
//ošetření výjimek typu TypN
}
finally {
//Kód, který se na závěr VŽDY provede
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
9
Náznak činnosti – řádný průběh
nedojde k vyvolání výjimky
= nedojde k chybě
try {
příkaz1();
příkaz2();
příkaz3();
}
catch ( xxxException e ) {
příkazProOšetřeníChyby();
}
Bloky catch
catch (…..
se přeskočí
finally {
ukončovacíPříkazy();
}
dalšíPříkaz();
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
12
Náznak činnosti – ošetřený výjimka
try {
příkaz1(); Při provádění metody příkaz2
dojde k ošetřené chybě
příkaz2();
příkaz3();
Byla vyhozena výjimka
tohoto typu nebo typu
}
některého z potomků
catch ( xxxException e ) {
příkazProOšetřeníChyby();
}
Ostatní bloky catch
catch (…..
se přeskočí
finally {
ukončovacíPříkazy();
}
dalšíPříkaz();
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
13
Náznak činnosti – neošetřená výjimka
Při provádění metody příkaz2
dojde k NEošetřené chybě
try {
příkaz1();
příkaz2();
příkaz3();
}
catch ( xxxException e ) {
příkazProOšetřeníChyby();
}
Ošetření nebylo nalezeno =>
catch (…..
provede se blok finally
a opouští se metoda
finally {
ukončovacíPříkazy();
}
dalšíPříkaz();
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
14
Vyvolání výjimky
public class Xyz implements Comparable
{
public bolean compareTo( Object o )
{
if( !(o instanceOf Xyz) )
throw new ClassCastException (
"\nPokus o porovnání s neporovnatelnou"
+ " instancí " + o );
//Zjištění, kdo je větší
return vysledek;
}
}
► Instanci nemusíme vytvářet až v příkazu throw,
můžeme ji vytvořit kdykoliv před tím a pak mu ji jen předat
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
15
Vaše jistota na trhu IT
Výjimky kontrolované a
nekontrolované
►Hierarchie výjimek
►Pořadí výjimek v blocích catch
►Metody generující výjimky
►Metody třídy Throwable
►Zřetězené výjimky
►Převod kontrolovaných na nekontrolované
Charakteristika
► Výjimky, které jsou potomky třídy RuntimeException
nebo Error označujeme jako nekontrolované (unchecked),
protože překladač nekontroluje, zda je na ně program připraven
► Ostatní výjimky označujeme jako kontrolované (checked),
protože překladač kontroluje dodržení pravidel:
● Každá metoda, která může vyhodit kontrolovanou výjimku,
se musí k této skutečnosti veřejně přihlásit
● Každé použití metody, která může vyhodit kontrolovanou výjimku,
musí být buď uzavřeno v bloku try…catch,
nebo se volající metoda musí přihlásit k tomu,
že může také vyhodit danou kontrolovanou výjimku
► Nekontrolované výjimky ohlašují chyby v programu,
kontrolované výjimky očekávatelné situace,
na jejichž výskyt má být program připraven
a měl by na ně umět reagovat
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
17
Hierarchie výjimek
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
18
Pořadí výjimek v blocích catch
► Třída NumberFormatException
je potomkem třídy RuntimeException
try {
Syntaktická chyba,
......
na druhý blok catch nikdy nedojde
}
catch (RuntimeException e) {
.........
}
Obrácené pořadí bloků catch
catch (NumberFormatException e){
vše vyřeší
........
try {
}
......
}
catch (NumberFormatException e) {
.........
}
catch (RuntimeException e){
........
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
19
Metody generující výjimky
► Java vyžaduje, aby programy, které používají metody
schopné vyvolat kontrolované výjimky,
byly o této schopnosti používaných metod informovány =>
pak vědí, které výjimku musí umět zachytit a ošetřit
► Všechny kontrolované výjimky, které může metoda vyhodit,
musí deklarovat v hlavičce za klíčovým slovem throws
► Deklarace vyhazování nekontrolovaných výjimek není povinná
public void metoda()
throws KontrolovanáVýjimka1,
KontrolovanáVýjimka2
{
// Tělo metody
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
20
Metody třídy Throwable
► String getMessage()
Vrátí zprávu popisující danou výjimku
► String toString()
Vrátí název třídy výjimky následovaný případnou zprávou
► void printStackTrace()
Vytiskne toString() následovaný sadou informací o volající
posloupnosti, která vedla k vzniku výjimky
► Throwable fillInStackTrace()
Připraví nové informace o volací posloupnosti
vedoucí k místu zavolání této metody
► StackTraceElement[] getStackTrace()
Vrátí uchované informace o volací posloupnosti dané výjimky
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
21
Zřetězené výjimky
► V některých situacích je vhodné v rámci ošetření výjimky vyvolat
jinou výjimku, a přitom umožnit zjistit,
která výjimka byla prvotním hybatelem celé akce
► Řada výjimek má mezi svými konstruktory i takové,
které akceptují jako poslední parametr
odkaz na výjimku, jež byla příčinou vyvolání dané výjimky
► Chce-li se program zeptat výjimky na výjimku, která ji způsobila,
použije metodu
public Throwable getCause()
► Ve zprávě o vyvolání výjimky jsou místa, kde byla jedna výjimka
nahrazena jinou, označována textem caused by:
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
22
Ukázka výpisu při zřetězení výjimek
HighLevelException: MidLevelException: LowLevelException
at Junk.a(Junk.java:13)
at Junk.main(Junk.java:4)
Caused by: MidLevelException: LowLevelException
at Junk.c(Junk.java:23)
at Junk.b(Junk.java:17)
at Junk.a(Junk.java:11)
... 1 more
Caused by: LowLevelException
at Junk.e(Junk.java:30)
at Junk.d(Junk.java:27)
at Junk.c(Junk.java:21)
... 3 more
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
23
Převod kontrolovaných na nekontrolované
► Ošetřování kontrolovaných výjimek obtěžuje
► Víme-li, že k dané výjimce nejspíš nedojde
a ošetřujeme-li ji pouze proto, že na tom překladač trvá,
můžeme pro případ, že by k výjimce přece jenom došlo
zaměnit kontrolovanou výjimku za nekontrolovanou
public void prevod( String s ) {
try {
prověř( s );
} catch( Exception ex ) {
throw new RuntimeException( " Neprověřeno! ", ex );
}
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
24
Vaše jistota na trhu IT
Definice vlastních výjimek
►Hierarchie výjimek
►Pořadí výjimek v blocích catch
►Metody generující výjimky
►Metody třídy Throwable
►Vlastní výjimky
►Zásady správného používání výjimek
Definice vlastních výjimek
► Výjimky jsou zcela běžné třídy;
považujeme-li to proto za vhodné, můžeme definovat i vlastní
► Před definicí nové výjimky bychom si měli ujasnit,
bude-li kontrolovaná či nekontrolovaná;
podle toho definujeme jejího předka
► Název výjimek končí dle konvencí slovem Exception
před nímž je naznačena podstata dané výjimky
● IllegalArgumetnException
● NoSuchMethodException
● BadStringOperationException
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
26
Příklad vlastní kontrolované výjimky
public class VelkýPrůšvihException
extends Exception
{
public VelkýPrůšvihException() {};
public VelkýPrůšvihException( String zpráva ) {
super( zpráva );
}
public VelkýPrůšvihException(String zpráva,
Throwable původce ) {
super( zpráva, původce );
}
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
27
Test správného vyhození výjimky
► Na vytvářených programech je třeba otestovat i to,
že v definovaných situacích vyhodí požadovanou výjimku
public void testVyhozeníVýjimky()
{
try {
metodaKteráMáVyhoditVýjimku();
} catch ( VelkýPrůšvihException vpe ) {
return;
}
fail( "Nebyla vyhozena výjimka VelkýPrůšvihException" );
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
28
Zásady správného používání výjimek
1/2
Neignorujte
výjimky
try {
//Nějaký kód
}
catch(Exception e){}
► Výjimky, o nichž víte, že nemohou nastat,
převeďte na nekontrolované pro případ,
že by v budoucích verzích programu nastat mohly
► Při ošetřování výjimek, které nastat mohou,
ale nemají vliv na chod programu,
vložte do těla ošetření alespoň vysvětlující komentář
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
29
Zásady správného používání výjimek
2/2
► Používejte výjimky pouze k ošetření výjimečných stavů
► Kontrolované výjimky používejte u stavů, z nichž se lze zotavit,
jinak použijte výjimky nekontrolované
► Vyhýbejte se zbytečnému používání kontrolovaných výjimek
● Programátory ošetřování kontrolovaných výjimek obtěžuje
a mají pak tendenci je ošetřovat prázdným blokem catch
► Dávejte přednost standardním výjimkám,
vyvolávejte výjimky odpovídající dané abstrakci
● Programátoři by měli z názvu výjimky poznat, co se stalo
● Standardní výjimky mají všeobecně známý význam
► Snažte se o atomičnost selhání; i po vyhození výjimky
by měl být objekt v dobře definovaném stavu
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
30
Zásady správného používání výjimek
3/2
► Doplňujte výjimky zprávami,
výjimka by sama měla poskytnout dostatek informací
a neměla by programátora nutit k podrobnější analýze programu
► Dokumentujte vyvolávané výjimky v dokumentačních
komentářích pomocí značky @throws
► Nedělejte bloky try zbytečně velké,
kód uvnitř těchto bloků se neoptimalizuje
► Umíte-li výjimku v metodě ošetřit, udělejte to
► Detekuje-li se chyba v jedné metodě a má se ošetřit v jiné
(stejné či jiné instance), použijte výjimku.
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
31
Nejčastěji používané výjimky
1/2
► IllegalArgumentException
Byla zadána nepovolená hodnota parametru
● Např. chci nastavit zápornou velikost grafického tvaru
► IllegalStateException
V daném stavu objektu nelze metodu provést
● Např. otevřu soubor, přečtu pár vět, zavřu soubor a chci znovu přečíst větu
► NullPointerException
Byla vyvolána metoda instance, na níž ukazuje prázdný odkaz,
nebo byl předán nepovolený prázdný odkaz v parametru
► ArrayIndexOutOfBoundException
Byly zadány špatné meze pole, buď záporné nebo moc velké
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
32
Nejčastěji používané výjimky
2/2
► ConcurrentModificationException
V průběhu iterace byla změněna struktura kontejneru
● Např. byl do kontejneru přidán prvek
► NumberFormatException
Je požadován špatný převod řetězce na číslo či naopak
● Chci-li např. převést na číslo řetězec, který není číslem
● Častá chyba v metodách String.format či PrintStream.printf
► ClassCastException
Požadované přetypování není možné
► UnsupportedOperationException
Požadovaná operace není podporována
(např. chci přidat prvek do neměnného kontejneru)
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
33
Vaše jistota na trhu IT
Děkuji za pozornost
►Rudolf Pecinovský
http://vyuka.pecinovsky.cz/vse
mail: [email protected]
ICQ: 158 156 600
Slide 10
Vaše jistota na trhu IT
Výjimky
Rudolf Pecinovský
[email protected]
Vaše jistota na trhu IT
Obsah s odkazy
►Výjimky
►Výjimky kontrolované a nekontrolované
►Definice vlastních výjimek
Vaše jistota na trhu IT
Výjimky
►Výjimečné situace v programech
►Ošetření nestandardních situací v Javě
►Zpráva o výjimce
►Klíčová slova
►Činnost
►Vyvolání
Výjimečné situace v programech
► V každém programu je alespoň jedna chyba –
program na ni musí být připraven
► Starší programy
● Program vypsal chybové hlášení a ukončil činnost;
● V některých situacích (válcovací stolice, autopilot, …) nepřijatelné
● Funkce vrátí hodnotu signalizující chybu
● Programátor musí neustále testovat, co funkce vrací
● Knihovna měla pro tyto účely vyhrazenu speciální proměnnou,
do níž se v případě chyby zapsal její kód; nahlédnutím do proměnné
program zjistil kód poslední chyby
● Programátor musí neustále testovat, jaká je v proměnné hodnota
► Některé jazyky (Cobol, PL/1, …) proto přišly s koncepcí
ošetření nestandardních situací
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
4
Ošetření nestandardních situací v Javě
► Výjimečná událost =
problém, který brání dalšímu vykonávání části kódu
► Událost je výjimečná v tom, že na rozdíl od běžných problémů
nemá program k vyřešení situace dost informaci
► Program může při výskytu výjimečné události vyvolat výjimku
► Výjimka (exception)
objekt určený k přenosu informací o nastalém problému
z místa jeho vzniku do místa, kde bude problém řešen
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
5
Postup při vyvolání výjimky
1. Vytvoří se výjimka = objekt typu Throwable
(prakticky vždy instance některého z potomků)
2. Vytvořená výjimka se vyhodí =
přeruší se běh programu v místě, kde výjimka vznikla,
a začne se hledat místo, kde bude daná výjimka ošetřena
3. Ošetření výjimky (handler) by mělo uvést program do stavu,
v němž může jeho vykonávání pokračovat
► Výjimka „probublává“ programem z místa vyhození stále výše
a nenarazí-li cestou nikde na své ošetření,
zachytí ji virtuální stroj, který na standardní chybový výstup
vypíše zprávu o vzniku výjimky
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
6
Systémová zpráva o vzniku výjimky
Zpráva o vzniku výjimky spolu s názvem vlákna,
v němž k výjimce došlo (zde AWT-EventQueue-0)
Popis druhu výjimky (aritmetická výjimka dělení nulou)
Informace o místě, odkud byla volána metoda,
která vyvolala metodu, v níž došlo k vyhození výjimky
Informace o místě, odkud byla volána metoda,
v níž došlo k vyhození výjimky
Úplný název třídy včetně balíčku
Copyright © 2006, Rudolf Pecinovský
Název metody
VŠE – 05
Název souboru se
zdrojovým kódem
Číslo řádku zdrojáku,
kde došlo k výjimce
7
Klíčová slova související s výjimkami
► try (zkus)
Označuje blok kódu, v němž může dojít k výjimce
► throw (hoď)
Příkaz k vyhození výjimky;
musí být následován odkazem na existující instanci
► catch (chyť)
Blok ošetřující výjimku, která je zadána jako parametr
► finally (na konec)
Blok s povinnými závěrečnými akcemi nezávisejícími
na případném vzniku výjimky
► throws (hází)
Uvození seznamu výjimek vyhazovaných danou metodou
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
8
Vyvolání a ošetření výjimky v kódu
try {
//Kód, který může vyvolat výjimky
}
catch( Typ1 id1 ) {
//Ošetření výjimek typu Typ1
}
...
catch( TypN idN ) {
//ošetření výjimek typu TypN
}
finally {
//Kód, který se na závěr VŽDY provede
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
9
Náznak činnosti – řádný průběh
nedojde k vyvolání výjimky
= nedojde k chybě
try {
příkaz1();
příkaz2();
příkaz3();
}
catch ( xxxException e ) {
příkazProOšetřeníChyby();
}
Bloky catch
catch (…..
se přeskočí
finally {
ukončovacíPříkazy();
}
dalšíPříkaz();
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
12
Náznak činnosti – ošetřený výjimka
try {
příkaz1(); Při provádění metody příkaz2
dojde k ošetřené chybě
příkaz2();
příkaz3();
Byla vyhozena výjimka
tohoto typu nebo typu
}
některého z potomků
catch ( xxxException e ) {
příkazProOšetřeníChyby();
}
Ostatní bloky catch
catch (…..
se přeskočí
finally {
ukončovacíPříkazy();
}
dalšíPříkaz();
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
13
Náznak činnosti – neošetřená výjimka
Při provádění metody příkaz2
dojde k NEošetřené chybě
try {
příkaz1();
příkaz2();
příkaz3();
}
catch ( xxxException e ) {
příkazProOšetřeníChyby();
}
Ošetření nebylo nalezeno =>
catch (…..
provede se blok finally
a opouští se metoda
finally {
ukončovacíPříkazy();
}
dalšíPříkaz();
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
14
Vyvolání výjimky
public class Xyz implements Comparable
{
public bolean compareTo( Object o )
{
if( !(o instanceOf Xyz) )
throw new ClassCastException (
"\nPokus o porovnání s neporovnatelnou"
+ " instancí " + o );
//Zjištění, kdo je větší
return vysledek;
}
}
► Instanci nemusíme vytvářet až v příkazu throw,
můžeme ji vytvořit kdykoliv před tím a pak mu ji jen předat
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
15
Vaše jistota na trhu IT
Výjimky kontrolované a
nekontrolované
►Hierarchie výjimek
►Pořadí výjimek v blocích catch
►Metody generující výjimky
►Metody třídy Throwable
►Zřetězené výjimky
►Převod kontrolovaných na nekontrolované
Charakteristika
► Výjimky, které jsou potomky třídy RuntimeException
nebo Error označujeme jako nekontrolované (unchecked),
protože překladač nekontroluje, zda je na ně program připraven
► Ostatní výjimky označujeme jako kontrolované (checked),
protože překladač kontroluje dodržení pravidel:
● Každá metoda, která může vyhodit kontrolovanou výjimku,
se musí k této skutečnosti veřejně přihlásit
● Každé použití metody, která může vyhodit kontrolovanou výjimku,
musí být buď uzavřeno v bloku try…catch,
nebo se volající metoda musí přihlásit k tomu,
že může také vyhodit danou kontrolovanou výjimku
► Nekontrolované výjimky ohlašují chyby v programu,
kontrolované výjimky očekávatelné situace,
na jejichž výskyt má být program připraven
a měl by na ně umět reagovat
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
17
Hierarchie výjimek
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
18
Pořadí výjimek v blocích catch
► Třída NumberFormatException
je potomkem třídy RuntimeException
try {
Syntaktická chyba,
......
na druhý blok catch nikdy nedojde
}
catch (RuntimeException e) {
.........
}
Obrácené pořadí bloků catch
catch (NumberFormatException e){
vše vyřeší
........
try {
}
......
}
catch (NumberFormatException e) {
.........
}
catch (RuntimeException e){
........
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
19
Metody generující výjimky
► Java vyžaduje, aby programy, které používají metody
schopné vyvolat kontrolované výjimky,
byly o této schopnosti používaných metod informovány =>
pak vědí, které výjimku musí umět zachytit a ošetřit
► Všechny kontrolované výjimky, které může metoda vyhodit,
musí deklarovat v hlavičce za klíčovým slovem throws
► Deklarace vyhazování nekontrolovaných výjimek není povinná
public void metoda()
throws KontrolovanáVýjimka1,
KontrolovanáVýjimka2
{
// Tělo metody
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
20
Metody třídy Throwable
► String getMessage()
Vrátí zprávu popisující danou výjimku
► String toString()
Vrátí název třídy výjimky následovaný případnou zprávou
► void printStackTrace()
Vytiskne toString() následovaný sadou informací o volající
posloupnosti, která vedla k vzniku výjimky
► Throwable fillInStackTrace()
Připraví nové informace o volací posloupnosti
vedoucí k místu zavolání této metody
► StackTraceElement[] getStackTrace()
Vrátí uchované informace o volací posloupnosti dané výjimky
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
21
Zřetězené výjimky
► V některých situacích je vhodné v rámci ošetření výjimky vyvolat
jinou výjimku, a přitom umožnit zjistit,
která výjimka byla prvotním hybatelem celé akce
► Řada výjimek má mezi svými konstruktory i takové,
které akceptují jako poslední parametr
odkaz na výjimku, jež byla příčinou vyvolání dané výjimky
► Chce-li se program zeptat výjimky na výjimku, která ji způsobila,
použije metodu
public Throwable getCause()
► Ve zprávě o vyvolání výjimky jsou místa, kde byla jedna výjimka
nahrazena jinou, označována textem caused by:
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
22
Ukázka výpisu při zřetězení výjimek
HighLevelException: MidLevelException: LowLevelException
at Junk.a(Junk.java:13)
at Junk.main(Junk.java:4)
Caused by: MidLevelException: LowLevelException
at Junk.c(Junk.java:23)
at Junk.b(Junk.java:17)
at Junk.a(Junk.java:11)
... 1 more
Caused by: LowLevelException
at Junk.e(Junk.java:30)
at Junk.d(Junk.java:27)
at Junk.c(Junk.java:21)
... 3 more
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
23
Převod kontrolovaných na nekontrolované
► Ošetřování kontrolovaných výjimek obtěžuje
► Víme-li, že k dané výjimce nejspíš nedojde
a ošetřujeme-li ji pouze proto, že na tom překladač trvá,
můžeme pro případ, že by k výjimce přece jenom došlo
zaměnit kontrolovanou výjimku za nekontrolovanou
public void prevod( String s ) {
try {
prověř( s );
} catch( Exception ex ) {
throw new RuntimeException( " Neprověřeno! ", ex );
}
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
24
Vaše jistota na trhu IT
Definice vlastních výjimek
►Hierarchie výjimek
►Pořadí výjimek v blocích catch
►Metody generující výjimky
►Metody třídy Throwable
►Vlastní výjimky
►Zásady správného používání výjimek
Definice vlastních výjimek
► Výjimky jsou zcela běžné třídy;
považujeme-li to proto za vhodné, můžeme definovat i vlastní
► Před definicí nové výjimky bychom si měli ujasnit,
bude-li kontrolovaná či nekontrolovaná;
podle toho definujeme jejího předka
► Název výjimek končí dle konvencí slovem Exception
před nímž je naznačena podstata dané výjimky
● IllegalArgumetnException
● NoSuchMethodException
● BadStringOperationException
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
26
Příklad vlastní kontrolované výjimky
public class VelkýPrůšvihException
extends Exception
{
public VelkýPrůšvihException() {};
public VelkýPrůšvihException( String zpráva ) {
super( zpráva );
}
public VelkýPrůšvihException(String zpráva,
Throwable původce ) {
super( zpráva, původce );
}
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
27
Test správného vyhození výjimky
► Na vytvářených programech je třeba otestovat i to,
že v definovaných situacích vyhodí požadovanou výjimku
public void testVyhozeníVýjimky()
{
try {
metodaKteráMáVyhoditVýjimku();
} catch ( VelkýPrůšvihException vpe ) {
return;
}
fail( "Nebyla vyhozena výjimka VelkýPrůšvihException" );
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
28
Zásady správného používání výjimek
1/2
Neignorujte
výjimky
try {
//Nějaký kód
}
catch(Exception e){}
► Výjimky, o nichž víte, že nemohou nastat,
převeďte na nekontrolované pro případ,
že by v budoucích verzích programu nastat mohly
► Při ošetřování výjimek, které nastat mohou,
ale nemají vliv na chod programu,
vložte do těla ošetření alespoň vysvětlující komentář
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
29
Zásady správného používání výjimek
2/2
► Používejte výjimky pouze k ošetření výjimečných stavů
► Kontrolované výjimky používejte u stavů, z nichž se lze zotavit,
jinak použijte výjimky nekontrolované
► Vyhýbejte se zbytečnému používání kontrolovaných výjimek
● Programátory ošetřování kontrolovaných výjimek obtěžuje
a mají pak tendenci je ošetřovat prázdným blokem catch
► Dávejte přednost standardním výjimkám,
vyvolávejte výjimky odpovídající dané abstrakci
● Programátoři by měli z názvu výjimky poznat, co se stalo
● Standardní výjimky mají všeobecně známý význam
► Snažte se o atomičnost selhání; i po vyhození výjimky
by měl být objekt v dobře definovaném stavu
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
30
Zásady správného používání výjimek
3/2
► Doplňujte výjimky zprávami,
výjimka by sama měla poskytnout dostatek informací
a neměla by programátora nutit k podrobnější analýze programu
► Dokumentujte vyvolávané výjimky v dokumentačních
komentářích pomocí značky @throws
► Nedělejte bloky try zbytečně velké,
kód uvnitř těchto bloků se neoptimalizuje
► Umíte-li výjimku v metodě ošetřit, udělejte to
► Detekuje-li se chyba v jedné metodě a má se ošetřit v jiné
(stejné či jiné instance), použijte výjimku.
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
31
Nejčastěji používané výjimky
1/2
► IllegalArgumentException
Byla zadána nepovolená hodnota parametru
● Např. chci nastavit zápornou velikost grafického tvaru
► IllegalStateException
V daném stavu objektu nelze metodu provést
● Např. otevřu soubor, přečtu pár vět, zavřu soubor a chci znovu přečíst větu
► NullPointerException
Byla vyvolána metoda instance, na níž ukazuje prázdný odkaz,
nebo byl předán nepovolený prázdný odkaz v parametru
► ArrayIndexOutOfBoundException
Byly zadány špatné meze pole, buď záporné nebo moc velké
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
32
Nejčastěji používané výjimky
2/2
► ConcurrentModificationException
V průběhu iterace byla změněna struktura kontejneru
● Např. byl do kontejneru přidán prvek
► NumberFormatException
Je požadován špatný převod řetězce na číslo či naopak
● Chci-li např. převést na číslo řetězec, který není číslem
● Častá chyba v metodách String.format či PrintStream.printf
► ClassCastException
Požadované přetypování není možné
► UnsupportedOperationException
Požadovaná operace není podporována
(např. chci přidat prvek do neměnného kontejneru)
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
33
Vaše jistota na trhu IT
Děkuji za pozornost
►Rudolf Pecinovský
http://vyuka.pecinovsky.cz/vse
mail: [email protected]
ICQ: 158 156 600
Slide 11
Vaše jistota na trhu IT
Výjimky
Rudolf Pecinovský
[email protected]
Vaše jistota na trhu IT
Obsah s odkazy
►Výjimky
►Výjimky kontrolované a nekontrolované
►Definice vlastních výjimek
Vaše jistota na trhu IT
Výjimky
►Výjimečné situace v programech
►Ošetření nestandardních situací v Javě
►Zpráva o výjimce
►Klíčová slova
►Činnost
►Vyvolání
Výjimečné situace v programech
► V každém programu je alespoň jedna chyba –
program na ni musí být připraven
► Starší programy
● Program vypsal chybové hlášení a ukončil činnost;
● V některých situacích (válcovací stolice, autopilot, …) nepřijatelné
● Funkce vrátí hodnotu signalizující chybu
● Programátor musí neustále testovat, co funkce vrací
● Knihovna měla pro tyto účely vyhrazenu speciální proměnnou,
do níž se v případě chyby zapsal její kód; nahlédnutím do proměnné
program zjistil kód poslední chyby
● Programátor musí neustále testovat, jaká je v proměnné hodnota
► Některé jazyky (Cobol, PL/1, …) proto přišly s koncepcí
ošetření nestandardních situací
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
4
Ošetření nestandardních situací v Javě
► Výjimečná událost =
problém, který brání dalšímu vykonávání části kódu
► Událost je výjimečná v tom, že na rozdíl od běžných problémů
nemá program k vyřešení situace dost informaci
► Program může při výskytu výjimečné události vyvolat výjimku
► Výjimka (exception)
objekt určený k přenosu informací o nastalém problému
z místa jeho vzniku do místa, kde bude problém řešen
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
5
Postup při vyvolání výjimky
1. Vytvoří se výjimka = objekt typu Throwable
(prakticky vždy instance některého z potomků)
2. Vytvořená výjimka se vyhodí =
přeruší se běh programu v místě, kde výjimka vznikla,
a začne se hledat místo, kde bude daná výjimka ošetřena
3. Ošetření výjimky (handler) by mělo uvést program do stavu,
v němž může jeho vykonávání pokračovat
► Výjimka „probublává“ programem z místa vyhození stále výše
a nenarazí-li cestou nikde na své ošetření,
zachytí ji virtuální stroj, který na standardní chybový výstup
vypíše zprávu o vzniku výjimky
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
6
Systémová zpráva o vzniku výjimky
Zpráva o vzniku výjimky spolu s názvem vlákna,
v němž k výjimce došlo (zde AWT-EventQueue-0)
Popis druhu výjimky (aritmetická výjimka dělení nulou)
Informace o místě, odkud byla volána metoda,
která vyvolala metodu, v níž došlo k vyhození výjimky
Informace o místě, odkud byla volána metoda,
v níž došlo k vyhození výjimky
Úplný název třídy včetně balíčku
Copyright © 2006, Rudolf Pecinovský
Název metody
VŠE – 05
Název souboru se
zdrojovým kódem
Číslo řádku zdrojáku,
kde došlo k výjimce
7
Klíčová slova související s výjimkami
► try (zkus)
Označuje blok kódu, v němž může dojít k výjimce
► throw (hoď)
Příkaz k vyhození výjimky;
musí být následován odkazem na existující instanci
► catch (chyť)
Blok ošetřující výjimku, která je zadána jako parametr
► finally (na konec)
Blok s povinnými závěrečnými akcemi nezávisejícími
na případném vzniku výjimky
► throws (hází)
Uvození seznamu výjimek vyhazovaných danou metodou
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
8
Vyvolání a ošetření výjimky v kódu
try {
//Kód, který může vyvolat výjimky
}
catch( Typ1 id1 ) {
//Ošetření výjimek typu Typ1
}
...
catch( TypN idN ) {
//ošetření výjimek typu TypN
}
finally {
//Kód, který se na závěr VŽDY provede
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
9
Náznak činnosti – řádný průběh
nedojde k vyvolání výjimky
= nedojde k chybě
try {
příkaz1();
příkaz2();
příkaz3();
}
catch ( xxxException e ) {
příkazProOšetřeníChyby();
}
Bloky catch
catch (…..
se přeskočí
finally {
ukončovacíPříkazy();
}
dalšíPříkaz();
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
12
Náznak činnosti – ošetřený výjimka
try {
příkaz1(); Při provádění metody příkaz2
dojde k ošetřené chybě
příkaz2();
příkaz3();
Byla vyhozena výjimka
tohoto typu nebo typu
}
některého z potomků
catch ( xxxException e ) {
příkazProOšetřeníChyby();
}
Ostatní bloky catch
catch (…..
se přeskočí
finally {
ukončovacíPříkazy();
}
dalšíPříkaz();
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
13
Náznak činnosti – neošetřená výjimka
Při provádění metody příkaz2
dojde k NEošetřené chybě
try {
příkaz1();
příkaz2();
příkaz3();
}
catch ( xxxException e ) {
příkazProOšetřeníChyby();
}
Ošetření nebylo nalezeno =>
catch (…..
provede se blok finally
a opouští se metoda
finally {
ukončovacíPříkazy();
}
dalšíPříkaz();
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
14
Vyvolání výjimky
public class Xyz implements Comparable
{
public bolean compareTo( Object o )
{
if( !(o instanceOf Xyz) )
throw new ClassCastException (
"\nPokus o porovnání s neporovnatelnou"
+ " instancí " + o );
//Zjištění, kdo je větší
return vysledek;
}
}
► Instanci nemusíme vytvářet až v příkazu throw,
můžeme ji vytvořit kdykoliv před tím a pak mu ji jen předat
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
15
Vaše jistota na trhu IT
Výjimky kontrolované a
nekontrolované
►Hierarchie výjimek
►Pořadí výjimek v blocích catch
►Metody generující výjimky
►Metody třídy Throwable
►Zřetězené výjimky
►Převod kontrolovaných na nekontrolované
Charakteristika
► Výjimky, které jsou potomky třídy RuntimeException
nebo Error označujeme jako nekontrolované (unchecked),
protože překladač nekontroluje, zda je na ně program připraven
► Ostatní výjimky označujeme jako kontrolované (checked),
protože překladač kontroluje dodržení pravidel:
● Každá metoda, která může vyhodit kontrolovanou výjimku,
se musí k této skutečnosti veřejně přihlásit
● Každé použití metody, která může vyhodit kontrolovanou výjimku,
musí být buď uzavřeno v bloku try…catch,
nebo se volající metoda musí přihlásit k tomu,
že může také vyhodit danou kontrolovanou výjimku
► Nekontrolované výjimky ohlašují chyby v programu,
kontrolované výjimky očekávatelné situace,
na jejichž výskyt má být program připraven
a měl by na ně umět reagovat
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
17
Hierarchie výjimek
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
18
Pořadí výjimek v blocích catch
► Třída NumberFormatException
je potomkem třídy RuntimeException
try {
Syntaktická chyba,
......
na druhý blok catch nikdy nedojde
}
catch (RuntimeException e) {
.........
}
Obrácené pořadí bloků catch
catch (NumberFormatException e){
vše vyřeší
........
try {
}
......
}
catch (NumberFormatException e) {
.........
}
catch (RuntimeException e){
........
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
19
Metody generující výjimky
► Java vyžaduje, aby programy, které používají metody
schopné vyvolat kontrolované výjimky,
byly o této schopnosti používaných metod informovány =>
pak vědí, které výjimku musí umět zachytit a ošetřit
► Všechny kontrolované výjimky, které může metoda vyhodit,
musí deklarovat v hlavičce za klíčovým slovem throws
► Deklarace vyhazování nekontrolovaných výjimek není povinná
public void metoda()
throws KontrolovanáVýjimka1,
KontrolovanáVýjimka2
{
// Tělo metody
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
20
Metody třídy Throwable
► String getMessage()
Vrátí zprávu popisující danou výjimku
► String toString()
Vrátí název třídy výjimky následovaný případnou zprávou
► void printStackTrace()
Vytiskne toString() následovaný sadou informací o volající
posloupnosti, která vedla k vzniku výjimky
► Throwable fillInStackTrace()
Připraví nové informace o volací posloupnosti
vedoucí k místu zavolání této metody
► StackTraceElement[] getStackTrace()
Vrátí uchované informace o volací posloupnosti dané výjimky
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
21
Zřetězené výjimky
► V některých situacích je vhodné v rámci ošetření výjimky vyvolat
jinou výjimku, a přitom umožnit zjistit,
která výjimka byla prvotním hybatelem celé akce
► Řada výjimek má mezi svými konstruktory i takové,
které akceptují jako poslední parametr
odkaz na výjimku, jež byla příčinou vyvolání dané výjimky
► Chce-li se program zeptat výjimky na výjimku, která ji způsobila,
použije metodu
public Throwable getCause()
► Ve zprávě o vyvolání výjimky jsou místa, kde byla jedna výjimka
nahrazena jinou, označována textem caused by:
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
22
Ukázka výpisu při zřetězení výjimek
HighLevelException: MidLevelException: LowLevelException
at Junk.a(Junk.java:13)
at Junk.main(Junk.java:4)
Caused by: MidLevelException: LowLevelException
at Junk.c(Junk.java:23)
at Junk.b(Junk.java:17)
at Junk.a(Junk.java:11)
... 1 more
Caused by: LowLevelException
at Junk.e(Junk.java:30)
at Junk.d(Junk.java:27)
at Junk.c(Junk.java:21)
... 3 more
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
23
Převod kontrolovaných na nekontrolované
► Ošetřování kontrolovaných výjimek obtěžuje
► Víme-li, že k dané výjimce nejspíš nedojde
a ošetřujeme-li ji pouze proto, že na tom překladač trvá,
můžeme pro případ, že by k výjimce přece jenom došlo
zaměnit kontrolovanou výjimku za nekontrolovanou
public void prevod( String s ) {
try {
prověř( s );
} catch( Exception ex ) {
throw new RuntimeException( " Neprověřeno! ", ex );
}
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
24
Vaše jistota na trhu IT
Definice vlastních výjimek
►Hierarchie výjimek
►Pořadí výjimek v blocích catch
►Metody generující výjimky
►Metody třídy Throwable
►Vlastní výjimky
►Zásady správného používání výjimek
Definice vlastních výjimek
► Výjimky jsou zcela běžné třídy;
považujeme-li to proto za vhodné, můžeme definovat i vlastní
► Před definicí nové výjimky bychom si měli ujasnit,
bude-li kontrolovaná či nekontrolovaná;
podle toho definujeme jejího předka
► Název výjimek končí dle konvencí slovem Exception
před nímž je naznačena podstata dané výjimky
● IllegalArgumetnException
● NoSuchMethodException
● BadStringOperationException
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
26
Příklad vlastní kontrolované výjimky
public class VelkýPrůšvihException
extends Exception
{
public VelkýPrůšvihException() {};
public VelkýPrůšvihException( String zpráva ) {
super( zpráva );
}
public VelkýPrůšvihException(String zpráva,
Throwable původce ) {
super( zpráva, původce );
}
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
27
Test správného vyhození výjimky
► Na vytvářených programech je třeba otestovat i to,
že v definovaných situacích vyhodí požadovanou výjimku
public void testVyhozeníVýjimky()
{
try {
metodaKteráMáVyhoditVýjimku();
} catch ( VelkýPrůšvihException vpe ) {
return;
}
fail( "Nebyla vyhozena výjimka VelkýPrůšvihException" );
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
28
Zásady správného používání výjimek
1/2
Neignorujte
výjimky
try {
//Nějaký kód
}
catch(Exception e){}
► Výjimky, o nichž víte, že nemohou nastat,
převeďte na nekontrolované pro případ,
že by v budoucích verzích programu nastat mohly
► Při ošetřování výjimek, které nastat mohou,
ale nemají vliv na chod programu,
vložte do těla ošetření alespoň vysvětlující komentář
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
29
Zásady správného používání výjimek
2/2
► Používejte výjimky pouze k ošetření výjimečných stavů
► Kontrolované výjimky používejte u stavů, z nichž se lze zotavit,
jinak použijte výjimky nekontrolované
► Vyhýbejte se zbytečnému používání kontrolovaných výjimek
● Programátory ošetřování kontrolovaných výjimek obtěžuje
a mají pak tendenci je ošetřovat prázdným blokem catch
► Dávejte přednost standardním výjimkám,
vyvolávejte výjimky odpovídající dané abstrakci
● Programátoři by měli z názvu výjimky poznat, co se stalo
● Standardní výjimky mají všeobecně známý význam
► Snažte se o atomičnost selhání; i po vyhození výjimky
by měl být objekt v dobře definovaném stavu
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
30
Zásady správného používání výjimek
3/2
► Doplňujte výjimky zprávami,
výjimka by sama měla poskytnout dostatek informací
a neměla by programátora nutit k podrobnější analýze programu
► Dokumentujte vyvolávané výjimky v dokumentačních
komentářích pomocí značky @throws
► Nedělejte bloky try zbytečně velké,
kód uvnitř těchto bloků se neoptimalizuje
► Umíte-li výjimku v metodě ošetřit, udělejte to
► Detekuje-li se chyba v jedné metodě a má se ošetřit v jiné
(stejné či jiné instance), použijte výjimku.
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
31
Nejčastěji používané výjimky
1/2
► IllegalArgumentException
Byla zadána nepovolená hodnota parametru
● Např. chci nastavit zápornou velikost grafického tvaru
► IllegalStateException
V daném stavu objektu nelze metodu provést
● Např. otevřu soubor, přečtu pár vět, zavřu soubor a chci znovu přečíst větu
► NullPointerException
Byla vyvolána metoda instance, na níž ukazuje prázdný odkaz,
nebo byl předán nepovolený prázdný odkaz v parametru
► ArrayIndexOutOfBoundException
Byly zadány špatné meze pole, buď záporné nebo moc velké
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
32
Nejčastěji používané výjimky
2/2
► ConcurrentModificationException
V průběhu iterace byla změněna struktura kontejneru
● Např. byl do kontejneru přidán prvek
► NumberFormatException
Je požadován špatný převod řetězce na číslo či naopak
● Chci-li např. převést na číslo řetězec, který není číslem
● Častá chyba v metodách String.format či PrintStream.printf
► ClassCastException
Požadované přetypování není možné
► UnsupportedOperationException
Požadovaná operace není podporována
(např. chci přidat prvek do neměnného kontejneru)
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
33
Vaše jistota na trhu IT
Děkuji za pozornost
►Rudolf Pecinovský
http://vyuka.pecinovsky.cz/vse
mail: [email protected]
ICQ: 158 156 600
Slide 12
Vaše jistota na trhu IT
Výjimky
Rudolf Pecinovský
[email protected]
Vaše jistota na trhu IT
Obsah s odkazy
►Výjimky
►Výjimky kontrolované a nekontrolované
►Definice vlastních výjimek
Vaše jistota na trhu IT
Výjimky
►Výjimečné situace v programech
►Ošetření nestandardních situací v Javě
►Zpráva o výjimce
►Klíčová slova
►Činnost
►Vyvolání
Výjimečné situace v programech
► V každém programu je alespoň jedna chyba –
program na ni musí být připraven
► Starší programy
● Program vypsal chybové hlášení a ukončil činnost;
● V některých situacích (válcovací stolice, autopilot, …) nepřijatelné
● Funkce vrátí hodnotu signalizující chybu
● Programátor musí neustále testovat, co funkce vrací
● Knihovna měla pro tyto účely vyhrazenu speciální proměnnou,
do níž se v případě chyby zapsal její kód; nahlédnutím do proměnné
program zjistil kód poslední chyby
● Programátor musí neustále testovat, jaká je v proměnné hodnota
► Některé jazyky (Cobol, PL/1, …) proto přišly s koncepcí
ošetření nestandardních situací
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
4
Ošetření nestandardních situací v Javě
► Výjimečná událost =
problém, který brání dalšímu vykonávání části kódu
► Událost je výjimečná v tom, že na rozdíl od běžných problémů
nemá program k vyřešení situace dost informaci
► Program může při výskytu výjimečné události vyvolat výjimku
► Výjimka (exception)
objekt určený k přenosu informací o nastalém problému
z místa jeho vzniku do místa, kde bude problém řešen
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
5
Postup při vyvolání výjimky
1. Vytvoří se výjimka = objekt typu Throwable
(prakticky vždy instance některého z potomků)
2. Vytvořená výjimka se vyhodí =
přeruší se běh programu v místě, kde výjimka vznikla,
a začne se hledat místo, kde bude daná výjimka ošetřena
3. Ošetření výjimky (handler) by mělo uvést program do stavu,
v němž může jeho vykonávání pokračovat
► Výjimka „probublává“ programem z místa vyhození stále výše
a nenarazí-li cestou nikde na své ošetření,
zachytí ji virtuální stroj, který na standardní chybový výstup
vypíše zprávu o vzniku výjimky
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
6
Systémová zpráva o vzniku výjimky
Zpráva o vzniku výjimky spolu s názvem vlákna,
v němž k výjimce došlo (zde AWT-EventQueue-0)
Popis druhu výjimky (aritmetická výjimka dělení nulou)
Informace o místě, odkud byla volána metoda,
která vyvolala metodu, v níž došlo k vyhození výjimky
Informace o místě, odkud byla volána metoda,
v níž došlo k vyhození výjimky
Úplný název třídy včetně balíčku
Copyright © 2006, Rudolf Pecinovský
Název metody
VŠE – 05
Název souboru se
zdrojovým kódem
Číslo řádku zdrojáku,
kde došlo k výjimce
7
Klíčová slova související s výjimkami
► try (zkus)
Označuje blok kódu, v němž může dojít k výjimce
► throw (hoď)
Příkaz k vyhození výjimky;
musí být následován odkazem na existující instanci
► catch (chyť)
Blok ošetřující výjimku, která je zadána jako parametr
► finally (na konec)
Blok s povinnými závěrečnými akcemi nezávisejícími
na případném vzniku výjimky
► throws (hází)
Uvození seznamu výjimek vyhazovaných danou metodou
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
8
Vyvolání a ošetření výjimky v kódu
try {
//Kód, který může vyvolat výjimky
}
catch( Typ1 id1 ) {
//Ošetření výjimek typu Typ1
}
...
catch( TypN idN ) {
//ošetření výjimek typu TypN
}
finally {
//Kód, který se na závěr VŽDY provede
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
9
Náznak činnosti – řádný průběh
nedojde k vyvolání výjimky
= nedojde k chybě
try {
příkaz1();
příkaz2();
příkaz3();
}
catch ( xxxException e ) {
příkazProOšetřeníChyby();
}
Bloky catch
catch (…..
se přeskočí
finally {
ukončovacíPříkazy();
}
dalšíPříkaz();
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
12
Náznak činnosti – ošetřený výjimka
try {
příkaz1(); Při provádění metody příkaz2
dojde k ošetřené chybě
příkaz2();
příkaz3();
Byla vyhozena výjimka
tohoto typu nebo typu
}
některého z potomků
catch ( xxxException e ) {
příkazProOšetřeníChyby();
}
Ostatní bloky catch
catch (…..
se přeskočí
finally {
ukončovacíPříkazy();
}
dalšíPříkaz();
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
13
Náznak činnosti – neošetřená výjimka
Při provádění metody příkaz2
dojde k NEošetřené chybě
try {
příkaz1();
příkaz2();
příkaz3();
}
catch ( xxxException e ) {
příkazProOšetřeníChyby();
}
Ošetření nebylo nalezeno =>
catch (…..
provede se blok finally
a opouští se metoda
finally {
ukončovacíPříkazy();
}
dalšíPříkaz();
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
14
Vyvolání výjimky
public class Xyz implements Comparable
{
public bolean compareTo( Object o )
{
if( !(o instanceOf Xyz) )
throw new ClassCastException (
"\nPokus o porovnání s neporovnatelnou"
+ " instancí " + o );
//Zjištění, kdo je větší
return vysledek;
}
}
► Instanci nemusíme vytvářet až v příkazu throw,
můžeme ji vytvořit kdykoliv před tím a pak mu ji jen předat
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
15
Vaše jistota na trhu IT
Výjimky kontrolované a
nekontrolované
►Hierarchie výjimek
►Pořadí výjimek v blocích catch
►Metody generující výjimky
►Metody třídy Throwable
►Zřetězené výjimky
►Převod kontrolovaných na nekontrolované
Charakteristika
► Výjimky, které jsou potomky třídy RuntimeException
nebo Error označujeme jako nekontrolované (unchecked),
protože překladač nekontroluje, zda je na ně program připraven
► Ostatní výjimky označujeme jako kontrolované (checked),
protože překladač kontroluje dodržení pravidel:
● Každá metoda, která může vyhodit kontrolovanou výjimku,
se musí k této skutečnosti veřejně přihlásit
● Každé použití metody, která může vyhodit kontrolovanou výjimku,
musí být buď uzavřeno v bloku try…catch,
nebo se volající metoda musí přihlásit k tomu,
že může také vyhodit danou kontrolovanou výjimku
► Nekontrolované výjimky ohlašují chyby v programu,
kontrolované výjimky očekávatelné situace,
na jejichž výskyt má být program připraven
a měl by na ně umět reagovat
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
17
Hierarchie výjimek
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
18
Pořadí výjimek v blocích catch
► Třída NumberFormatException
je potomkem třídy RuntimeException
try {
Syntaktická chyba,
......
na druhý blok catch nikdy nedojde
}
catch (RuntimeException e) {
.........
}
Obrácené pořadí bloků catch
catch (NumberFormatException e){
vše vyřeší
........
try {
}
......
}
catch (NumberFormatException e) {
.........
}
catch (RuntimeException e){
........
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
19
Metody generující výjimky
► Java vyžaduje, aby programy, které používají metody
schopné vyvolat kontrolované výjimky,
byly o této schopnosti používaných metod informovány =>
pak vědí, které výjimku musí umět zachytit a ošetřit
► Všechny kontrolované výjimky, které může metoda vyhodit,
musí deklarovat v hlavičce za klíčovým slovem throws
► Deklarace vyhazování nekontrolovaných výjimek není povinná
public void metoda()
throws KontrolovanáVýjimka1,
KontrolovanáVýjimka2
{
// Tělo metody
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
20
Metody třídy Throwable
► String getMessage()
Vrátí zprávu popisující danou výjimku
► String toString()
Vrátí název třídy výjimky následovaný případnou zprávou
► void printStackTrace()
Vytiskne toString() následovaný sadou informací o volající
posloupnosti, která vedla k vzniku výjimky
► Throwable fillInStackTrace()
Připraví nové informace o volací posloupnosti
vedoucí k místu zavolání této metody
► StackTraceElement[] getStackTrace()
Vrátí uchované informace o volací posloupnosti dané výjimky
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
21
Zřetězené výjimky
► V některých situacích je vhodné v rámci ošetření výjimky vyvolat
jinou výjimku, a přitom umožnit zjistit,
která výjimka byla prvotním hybatelem celé akce
► Řada výjimek má mezi svými konstruktory i takové,
které akceptují jako poslední parametr
odkaz na výjimku, jež byla příčinou vyvolání dané výjimky
► Chce-li se program zeptat výjimky na výjimku, která ji způsobila,
použije metodu
public Throwable getCause()
► Ve zprávě o vyvolání výjimky jsou místa, kde byla jedna výjimka
nahrazena jinou, označována textem caused by:
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
22
Ukázka výpisu při zřetězení výjimek
HighLevelException: MidLevelException: LowLevelException
at Junk.a(Junk.java:13)
at Junk.main(Junk.java:4)
Caused by: MidLevelException: LowLevelException
at Junk.c(Junk.java:23)
at Junk.b(Junk.java:17)
at Junk.a(Junk.java:11)
... 1 more
Caused by: LowLevelException
at Junk.e(Junk.java:30)
at Junk.d(Junk.java:27)
at Junk.c(Junk.java:21)
... 3 more
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
23
Převod kontrolovaných na nekontrolované
► Ošetřování kontrolovaných výjimek obtěžuje
► Víme-li, že k dané výjimce nejspíš nedojde
a ošetřujeme-li ji pouze proto, že na tom překladač trvá,
můžeme pro případ, že by k výjimce přece jenom došlo
zaměnit kontrolovanou výjimku za nekontrolovanou
public void prevod( String s ) {
try {
prověř( s );
} catch( Exception ex ) {
throw new RuntimeException( " Neprověřeno! ", ex );
}
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
24
Vaše jistota na trhu IT
Definice vlastních výjimek
►Hierarchie výjimek
►Pořadí výjimek v blocích catch
►Metody generující výjimky
►Metody třídy Throwable
►Vlastní výjimky
►Zásady správného používání výjimek
Definice vlastních výjimek
► Výjimky jsou zcela běžné třídy;
považujeme-li to proto za vhodné, můžeme definovat i vlastní
► Před definicí nové výjimky bychom si měli ujasnit,
bude-li kontrolovaná či nekontrolovaná;
podle toho definujeme jejího předka
► Název výjimek končí dle konvencí slovem Exception
před nímž je naznačena podstata dané výjimky
● IllegalArgumetnException
● NoSuchMethodException
● BadStringOperationException
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
26
Příklad vlastní kontrolované výjimky
public class VelkýPrůšvihException
extends Exception
{
public VelkýPrůšvihException() {};
public VelkýPrůšvihException( String zpráva ) {
super( zpráva );
}
public VelkýPrůšvihException(String zpráva,
Throwable původce ) {
super( zpráva, původce );
}
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
27
Test správného vyhození výjimky
► Na vytvářených programech je třeba otestovat i to,
že v definovaných situacích vyhodí požadovanou výjimku
public void testVyhozeníVýjimky()
{
try {
metodaKteráMáVyhoditVýjimku();
} catch ( VelkýPrůšvihException vpe ) {
return;
}
fail( "Nebyla vyhozena výjimka VelkýPrůšvihException" );
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
28
Zásady správného používání výjimek
1/2
Neignorujte
výjimky
try {
//Nějaký kód
}
catch(Exception e){}
► Výjimky, o nichž víte, že nemohou nastat,
převeďte na nekontrolované pro případ,
že by v budoucích verzích programu nastat mohly
► Při ošetřování výjimek, které nastat mohou,
ale nemají vliv na chod programu,
vložte do těla ošetření alespoň vysvětlující komentář
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
29
Zásady správného používání výjimek
2/2
► Používejte výjimky pouze k ošetření výjimečných stavů
► Kontrolované výjimky používejte u stavů, z nichž se lze zotavit,
jinak použijte výjimky nekontrolované
► Vyhýbejte se zbytečnému používání kontrolovaných výjimek
● Programátory ošetřování kontrolovaných výjimek obtěžuje
a mají pak tendenci je ošetřovat prázdným blokem catch
► Dávejte přednost standardním výjimkám,
vyvolávejte výjimky odpovídající dané abstrakci
● Programátoři by měli z názvu výjimky poznat, co se stalo
● Standardní výjimky mají všeobecně známý význam
► Snažte se o atomičnost selhání; i po vyhození výjimky
by měl být objekt v dobře definovaném stavu
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
30
Zásady správného používání výjimek
3/2
► Doplňujte výjimky zprávami,
výjimka by sama měla poskytnout dostatek informací
a neměla by programátora nutit k podrobnější analýze programu
► Dokumentujte vyvolávané výjimky v dokumentačních
komentářích pomocí značky @throws
► Nedělejte bloky try zbytečně velké,
kód uvnitř těchto bloků se neoptimalizuje
► Umíte-li výjimku v metodě ošetřit, udělejte to
► Detekuje-li se chyba v jedné metodě a má se ošetřit v jiné
(stejné či jiné instance), použijte výjimku.
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
31
Nejčastěji používané výjimky
1/2
► IllegalArgumentException
Byla zadána nepovolená hodnota parametru
● Např. chci nastavit zápornou velikost grafického tvaru
► IllegalStateException
V daném stavu objektu nelze metodu provést
● Např. otevřu soubor, přečtu pár vět, zavřu soubor a chci znovu přečíst větu
► NullPointerException
Byla vyvolána metoda instance, na níž ukazuje prázdný odkaz,
nebo byl předán nepovolený prázdný odkaz v parametru
► ArrayIndexOutOfBoundException
Byly zadány špatné meze pole, buď záporné nebo moc velké
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
32
Nejčastěji používané výjimky
2/2
► ConcurrentModificationException
V průběhu iterace byla změněna struktura kontejneru
● Např. byl do kontejneru přidán prvek
► NumberFormatException
Je požadován špatný převod řetězce na číslo či naopak
● Chci-li např. převést na číslo řetězec, který není číslem
● Častá chyba v metodách String.format či PrintStream.printf
► ClassCastException
Požadované přetypování není možné
► UnsupportedOperationException
Požadovaná operace není podporována
(např. chci přidat prvek do neměnného kontejneru)
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
33
Vaše jistota na trhu IT
Děkuji za pozornost
►Rudolf Pecinovský
http://vyuka.pecinovsky.cz/vse
mail: [email protected]
ICQ: 158 156 600
Slide 13
Vaše jistota na trhu IT
Výjimky
Rudolf Pecinovský
[email protected]
Vaše jistota na trhu IT
Obsah s odkazy
►Výjimky
►Výjimky kontrolované a nekontrolované
►Definice vlastních výjimek
Vaše jistota na trhu IT
Výjimky
►Výjimečné situace v programech
►Ošetření nestandardních situací v Javě
►Zpráva o výjimce
►Klíčová slova
►Činnost
►Vyvolání
Výjimečné situace v programech
► V každém programu je alespoň jedna chyba –
program na ni musí být připraven
► Starší programy
● Program vypsal chybové hlášení a ukončil činnost;
● V některých situacích (válcovací stolice, autopilot, …) nepřijatelné
● Funkce vrátí hodnotu signalizující chybu
● Programátor musí neustále testovat, co funkce vrací
● Knihovna měla pro tyto účely vyhrazenu speciální proměnnou,
do níž se v případě chyby zapsal její kód; nahlédnutím do proměnné
program zjistil kód poslední chyby
● Programátor musí neustále testovat, jaká je v proměnné hodnota
► Některé jazyky (Cobol, PL/1, …) proto přišly s koncepcí
ošetření nestandardních situací
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
4
Ošetření nestandardních situací v Javě
► Výjimečná událost =
problém, který brání dalšímu vykonávání části kódu
► Událost je výjimečná v tom, že na rozdíl od běžných problémů
nemá program k vyřešení situace dost informaci
► Program může při výskytu výjimečné události vyvolat výjimku
► Výjimka (exception)
objekt určený k přenosu informací o nastalém problému
z místa jeho vzniku do místa, kde bude problém řešen
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
5
Postup při vyvolání výjimky
1. Vytvoří se výjimka = objekt typu Throwable
(prakticky vždy instance některého z potomků)
2. Vytvořená výjimka se vyhodí =
přeruší se běh programu v místě, kde výjimka vznikla,
a začne se hledat místo, kde bude daná výjimka ošetřena
3. Ošetření výjimky (handler) by mělo uvést program do stavu,
v němž může jeho vykonávání pokračovat
► Výjimka „probublává“ programem z místa vyhození stále výše
a nenarazí-li cestou nikde na své ošetření,
zachytí ji virtuální stroj, který na standardní chybový výstup
vypíše zprávu o vzniku výjimky
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
6
Systémová zpráva o vzniku výjimky
Zpráva o vzniku výjimky spolu s názvem vlákna,
v němž k výjimce došlo (zde AWT-EventQueue-0)
Popis druhu výjimky (aritmetická výjimka dělení nulou)
Informace o místě, odkud byla volána metoda,
která vyvolala metodu, v níž došlo k vyhození výjimky
Informace o místě, odkud byla volána metoda,
v níž došlo k vyhození výjimky
Úplný název třídy včetně balíčku
Copyright © 2006, Rudolf Pecinovský
Název metody
VŠE – 05
Název souboru se
zdrojovým kódem
Číslo řádku zdrojáku,
kde došlo k výjimce
7
Klíčová slova související s výjimkami
► try (zkus)
Označuje blok kódu, v němž může dojít k výjimce
► throw (hoď)
Příkaz k vyhození výjimky;
musí být následován odkazem na existující instanci
► catch (chyť)
Blok ošetřující výjimku, která je zadána jako parametr
► finally (na konec)
Blok s povinnými závěrečnými akcemi nezávisejícími
na případném vzniku výjimky
► throws (hází)
Uvození seznamu výjimek vyhazovaných danou metodou
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
8
Vyvolání a ošetření výjimky v kódu
try {
//Kód, který může vyvolat výjimky
}
catch( Typ1 id1 ) {
//Ošetření výjimek typu Typ1
}
...
catch( TypN idN ) {
//ošetření výjimek typu TypN
}
finally {
//Kód, který se na závěr VŽDY provede
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
9
Náznak činnosti – řádný průběh
nedojde k vyvolání výjimky
= nedojde k chybě
try {
příkaz1();
příkaz2();
příkaz3();
}
catch ( xxxException e ) {
příkazProOšetřeníChyby();
}
Bloky catch
catch (…..
se přeskočí
finally {
ukončovacíPříkazy();
}
dalšíPříkaz();
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
12
Náznak činnosti – ošetřený výjimka
try {
příkaz1(); Při provádění metody příkaz2
dojde k ošetřené chybě
příkaz2();
příkaz3();
Byla vyhozena výjimka
tohoto typu nebo typu
}
některého z potomků
catch ( xxxException e ) {
příkazProOšetřeníChyby();
}
Ostatní bloky catch
catch (…..
se přeskočí
finally {
ukončovacíPříkazy();
}
dalšíPříkaz();
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
13
Náznak činnosti – neošetřená výjimka
Při provádění metody příkaz2
dojde k NEošetřené chybě
try {
příkaz1();
příkaz2();
příkaz3();
}
catch ( xxxException e ) {
příkazProOšetřeníChyby();
}
Ošetření nebylo nalezeno =>
catch (…..
provede se blok finally
a opouští se metoda
finally {
ukončovacíPříkazy();
}
dalšíPříkaz();
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
14
Vyvolání výjimky
public class Xyz implements Comparable
{
public bolean compareTo( Object o )
{
if( !(o instanceOf Xyz) )
throw new ClassCastException (
"\nPokus o porovnání s neporovnatelnou"
+ " instancí " + o );
//Zjištění, kdo je větší
return vysledek;
}
}
► Instanci nemusíme vytvářet až v příkazu throw,
můžeme ji vytvořit kdykoliv před tím a pak mu ji jen předat
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
15
Vaše jistota na trhu IT
Výjimky kontrolované a
nekontrolované
►Hierarchie výjimek
►Pořadí výjimek v blocích catch
►Metody generující výjimky
►Metody třídy Throwable
►Zřetězené výjimky
►Převod kontrolovaných na nekontrolované
Charakteristika
► Výjimky, které jsou potomky třídy RuntimeException
nebo Error označujeme jako nekontrolované (unchecked),
protože překladač nekontroluje, zda je na ně program připraven
► Ostatní výjimky označujeme jako kontrolované (checked),
protože překladač kontroluje dodržení pravidel:
● Každá metoda, která může vyhodit kontrolovanou výjimku,
se musí k této skutečnosti veřejně přihlásit
● Každé použití metody, která může vyhodit kontrolovanou výjimku,
musí být buď uzavřeno v bloku try…catch,
nebo se volající metoda musí přihlásit k tomu,
že může také vyhodit danou kontrolovanou výjimku
► Nekontrolované výjimky ohlašují chyby v programu,
kontrolované výjimky očekávatelné situace,
na jejichž výskyt má být program připraven
a měl by na ně umět reagovat
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
17
Hierarchie výjimek
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
18
Pořadí výjimek v blocích catch
► Třída NumberFormatException
je potomkem třídy RuntimeException
try {
Syntaktická chyba,
......
na druhý blok catch nikdy nedojde
}
catch (RuntimeException e) {
.........
}
Obrácené pořadí bloků catch
catch (NumberFormatException e){
vše vyřeší
........
try {
}
......
}
catch (NumberFormatException e) {
.........
}
catch (RuntimeException e){
........
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
19
Metody generující výjimky
► Java vyžaduje, aby programy, které používají metody
schopné vyvolat kontrolované výjimky,
byly o této schopnosti používaných metod informovány =>
pak vědí, které výjimku musí umět zachytit a ošetřit
► Všechny kontrolované výjimky, které může metoda vyhodit,
musí deklarovat v hlavičce za klíčovým slovem throws
► Deklarace vyhazování nekontrolovaných výjimek není povinná
public void metoda()
throws KontrolovanáVýjimka1,
KontrolovanáVýjimka2
{
// Tělo metody
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
20
Metody třídy Throwable
► String getMessage()
Vrátí zprávu popisující danou výjimku
► String toString()
Vrátí název třídy výjimky následovaný případnou zprávou
► void printStackTrace()
Vytiskne toString() následovaný sadou informací o volající
posloupnosti, která vedla k vzniku výjimky
► Throwable fillInStackTrace()
Připraví nové informace o volací posloupnosti
vedoucí k místu zavolání této metody
► StackTraceElement[] getStackTrace()
Vrátí uchované informace o volací posloupnosti dané výjimky
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
21
Zřetězené výjimky
► V některých situacích je vhodné v rámci ošetření výjimky vyvolat
jinou výjimku, a přitom umožnit zjistit,
která výjimka byla prvotním hybatelem celé akce
► Řada výjimek má mezi svými konstruktory i takové,
které akceptují jako poslední parametr
odkaz na výjimku, jež byla příčinou vyvolání dané výjimky
► Chce-li se program zeptat výjimky na výjimku, která ji způsobila,
použije metodu
public Throwable getCause()
► Ve zprávě o vyvolání výjimky jsou místa, kde byla jedna výjimka
nahrazena jinou, označována textem caused by:
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
22
Ukázka výpisu při zřetězení výjimek
HighLevelException: MidLevelException: LowLevelException
at Junk.a(Junk.java:13)
at Junk.main(Junk.java:4)
Caused by: MidLevelException: LowLevelException
at Junk.c(Junk.java:23)
at Junk.b(Junk.java:17)
at Junk.a(Junk.java:11)
... 1 more
Caused by: LowLevelException
at Junk.e(Junk.java:30)
at Junk.d(Junk.java:27)
at Junk.c(Junk.java:21)
... 3 more
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
23
Převod kontrolovaných na nekontrolované
► Ošetřování kontrolovaných výjimek obtěžuje
► Víme-li, že k dané výjimce nejspíš nedojde
a ošetřujeme-li ji pouze proto, že na tom překladač trvá,
můžeme pro případ, že by k výjimce přece jenom došlo
zaměnit kontrolovanou výjimku za nekontrolovanou
public void prevod( String s ) {
try {
prověř( s );
} catch( Exception ex ) {
throw new RuntimeException( " Neprověřeno! ", ex );
}
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
24
Vaše jistota na trhu IT
Definice vlastních výjimek
►Hierarchie výjimek
►Pořadí výjimek v blocích catch
►Metody generující výjimky
►Metody třídy Throwable
►Vlastní výjimky
►Zásady správného používání výjimek
Definice vlastních výjimek
► Výjimky jsou zcela běžné třídy;
považujeme-li to proto za vhodné, můžeme definovat i vlastní
► Před definicí nové výjimky bychom si měli ujasnit,
bude-li kontrolovaná či nekontrolovaná;
podle toho definujeme jejího předka
► Název výjimek končí dle konvencí slovem Exception
před nímž je naznačena podstata dané výjimky
● IllegalArgumetnException
● NoSuchMethodException
● BadStringOperationException
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
26
Příklad vlastní kontrolované výjimky
public class VelkýPrůšvihException
extends Exception
{
public VelkýPrůšvihException() {};
public VelkýPrůšvihException( String zpráva ) {
super( zpráva );
}
public VelkýPrůšvihException(String zpráva,
Throwable původce ) {
super( zpráva, původce );
}
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
27
Test správného vyhození výjimky
► Na vytvářených programech je třeba otestovat i to,
že v definovaných situacích vyhodí požadovanou výjimku
public void testVyhozeníVýjimky()
{
try {
metodaKteráMáVyhoditVýjimku();
} catch ( VelkýPrůšvihException vpe ) {
return;
}
fail( "Nebyla vyhozena výjimka VelkýPrůšvihException" );
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
28
Zásady správného používání výjimek
1/2
Neignorujte
výjimky
try {
//Nějaký kód
}
catch(Exception e){}
► Výjimky, o nichž víte, že nemohou nastat,
převeďte na nekontrolované pro případ,
že by v budoucích verzích programu nastat mohly
► Při ošetřování výjimek, které nastat mohou,
ale nemají vliv na chod programu,
vložte do těla ošetření alespoň vysvětlující komentář
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
29
Zásady správného používání výjimek
2/2
► Používejte výjimky pouze k ošetření výjimečných stavů
► Kontrolované výjimky používejte u stavů, z nichž se lze zotavit,
jinak použijte výjimky nekontrolované
► Vyhýbejte se zbytečnému používání kontrolovaných výjimek
● Programátory ošetřování kontrolovaných výjimek obtěžuje
a mají pak tendenci je ošetřovat prázdným blokem catch
► Dávejte přednost standardním výjimkám,
vyvolávejte výjimky odpovídající dané abstrakci
● Programátoři by měli z názvu výjimky poznat, co se stalo
● Standardní výjimky mají všeobecně známý význam
► Snažte se o atomičnost selhání; i po vyhození výjimky
by měl být objekt v dobře definovaném stavu
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
30
Zásady správného používání výjimek
3/2
► Doplňujte výjimky zprávami,
výjimka by sama měla poskytnout dostatek informací
a neměla by programátora nutit k podrobnější analýze programu
► Dokumentujte vyvolávané výjimky v dokumentačních
komentářích pomocí značky @throws
► Nedělejte bloky try zbytečně velké,
kód uvnitř těchto bloků se neoptimalizuje
► Umíte-li výjimku v metodě ošetřit, udělejte to
► Detekuje-li se chyba v jedné metodě a má se ošetřit v jiné
(stejné či jiné instance), použijte výjimku.
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
31
Nejčastěji používané výjimky
1/2
► IllegalArgumentException
Byla zadána nepovolená hodnota parametru
● Např. chci nastavit zápornou velikost grafického tvaru
► IllegalStateException
V daném stavu objektu nelze metodu provést
● Např. otevřu soubor, přečtu pár vět, zavřu soubor a chci znovu přečíst větu
► NullPointerException
Byla vyvolána metoda instance, na níž ukazuje prázdný odkaz,
nebo byl předán nepovolený prázdný odkaz v parametru
► ArrayIndexOutOfBoundException
Byly zadány špatné meze pole, buď záporné nebo moc velké
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
32
Nejčastěji používané výjimky
2/2
► ConcurrentModificationException
V průběhu iterace byla změněna struktura kontejneru
● Např. byl do kontejneru přidán prvek
► NumberFormatException
Je požadován špatný převod řetězce na číslo či naopak
● Chci-li např. převést na číslo řetězec, který není číslem
● Častá chyba v metodách String.format či PrintStream.printf
► ClassCastException
Požadované přetypování není možné
► UnsupportedOperationException
Požadovaná operace není podporována
(např. chci přidat prvek do neměnného kontejneru)
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
33
Vaše jistota na trhu IT
Děkuji za pozornost
►Rudolf Pecinovský
http://vyuka.pecinovsky.cz/vse
mail: [email protected]
ICQ: 158 156 600
Slide 14
Vaše jistota na trhu IT
Výjimky
Rudolf Pecinovský
[email protected]
Vaše jistota na trhu IT
Obsah s odkazy
►Výjimky
►Výjimky kontrolované a nekontrolované
►Definice vlastních výjimek
Vaše jistota na trhu IT
Výjimky
►Výjimečné situace v programech
►Ošetření nestandardních situací v Javě
►Zpráva o výjimce
►Klíčová slova
►Činnost
►Vyvolání
Výjimečné situace v programech
► V každém programu je alespoň jedna chyba –
program na ni musí být připraven
► Starší programy
● Program vypsal chybové hlášení a ukončil činnost;
● V některých situacích (válcovací stolice, autopilot, …) nepřijatelné
● Funkce vrátí hodnotu signalizující chybu
● Programátor musí neustále testovat, co funkce vrací
● Knihovna měla pro tyto účely vyhrazenu speciální proměnnou,
do níž se v případě chyby zapsal její kód; nahlédnutím do proměnné
program zjistil kód poslední chyby
● Programátor musí neustále testovat, jaká je v proměnné hodnota
► Některé jazyky (Cobol, PL/1, …) proto přišly s koncepcí
ošetření nestandardních situací
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
4
Ošetření nestandardních situací v Javě
► Výjimečná událost =
problém, který brání dalšímu vykonávání části kódu
► Událost je výjimečná v tom, že na rozdíl od běžných problémů
nemá program k vyřešení situace dost informaci
► Program může při výskytu výjimečné události vyvolat výjimku
► Výjimka (exception)
objekt určený k přenosu informací o nastalém problému
z místa jeho vzniku do místa, kde bude problém řešen
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
5
Postup při vyvolání výjimky
1. Vytvoří se výjimka = objekt typu Throwable
(prakticky vždy instance některého z potomků)
2. Vytvořená výjimka se vyhodí =
přeruší se běh programu v místě, kde výjimka vznikla,
a začne se hledat místo, kde bude daná výjimka ošetřena
3. Ošetření výjimky (handler) by mělo uvést program do stavu,
v němž může jeho vykonávání pokračovat
► Výjimka „probublává“ programem z místa vyhození stále výše
a nenarazí-li cestou nikde na své ošetření,
zachytí ji virtuální stroj, který na standardní chybový výstup
vypíše zprávu o vzniku výjimky
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
6
Systémová zpráva o vzniku výjimky
Zpráva o vzniku výjimky spolu s názvem vlákna,
v němž k výjimce došlo (zde AWT-EventQueue-0)
Popis druhu výjimky (aritmetická výjimka dělení nulou)
Informace o místě, odkud byla volána metoda,
která vyvolala metodu, v níž došlo k vyhození výjimky
Informace o místě, odkud byla volána metoda,
v níž došlo k vyhození výjimky
Úplný název třídy včetně balíčku
Copyright © 2006, Rudolf Pecinovský
Název metody
VŠE – 05
Název souboru se
zdrojovým kódem
Číslo řádku zdrojáku,
kde došlo k výjimce
7
Klíčová slova související s výjimkami
► try (zkus)
Označuje blok kódu, v němž může dojít k výjimce
► throw (hoď)
Příkaz k vyhození výjimky;
musí být následován odkazem na existující instanci
► catch (chyť)
Blok ošetřující výjimku, která je zadána jako parametr
► finally (na konec)
Blok s povinnými závěrečnými akcemi nezávisejícími
na případném vzniku výjimky
► throws (hází)
Uvození seznamu výjimek vyhazovaných danou metodou
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
8
Vyvolání a ošetření výjimky v kódu
try {
//Kód, který může vyvolat výjimky
}
catch( Typ1 id1 ) {
//Ošetření výjimek typu Typ1
}
...
catch( TypN idN ) {
//ošetření výjimek typu TypN
}
finally {
//Kód, který se na závěr VŽDY provede
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
9
Náznak činnosti – řádný průběh
nedojde k vyvolání výjimky
= nedojde k chybě
try {
příkaz1();
příkaz2();
příkaz3();
}
catch ( xxxException e ) {
příkazProOšetřeníChyby();
}
Bloky catch
catch (…..
se přeskočí
finally {
ukončovacíPříkazy();
}
dalšíPříkaz();
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
12
Náznak činnosti – ošetřený výjimka
try {
příkaz1(); Při provádění metody příkaz2
dojde k ošetřené chybě
příkaz2();
příkaz3();
Byla vyhozena výjimka
tohoto typu nebo typu
}
některého z potomků
catch ( xxxException e ) {
příkazProOšetřeníChyby();
}
Ostatní bloky catch
catch (…..
se přeskočí
finally {
ukončovacíPříkazy();
}
dalšíPříkaz();
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
13
Náznak činnosti – neošetřená výjimka
Při provádění metody příkaz2
dojde k NEošetřené chybě
try {
příkaz1();
příkaz2();
příkaz3();
}
catch ( xxxException e ) {
příkazProOšetřeníChyby();
}
Ošetření nebylo nalezeno =>
catch (…..
provede se blok finally
a opouští se metoda
finally {
ukončovacíPříkazy();
}
dalšíPříkaz();
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
14
Vyvolání výjimky
public class Xyz implements Comparable
{
public bolean compareTo( Object o )
{
if( !(o instanceOf Xyz) )
throw new ClassCastException (
"\nPokus o porovnání s neporovnatelnou"
+ " instancí " + o );
//Zjištění, kdo je větší
return vysledek;
}
}
► Instanci nemusíme vytvářet až v příkazu throw,
můžeme ji vytvořit kdykoliv před tím a pak mu ji jen předat
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
15
Vaše jistota na trhu IT
Výjimky kontrolované a
nekontrolované
►Hierarchie výjimek
►Pořadí výjimek v blocích catch
►Metody generující výjimky
►Metody třídy Throwable
►Zřetězené výjimky
►Převod kontrolovaných na nekontrolované
Charakteristika
► Výjimky, které jsou potomky třídy RuntimeException
nebo Error označujeme jako nekontrolované (unchecked),
protože překladač nekontroluje, zda je na ně program připraven
► Ostatní výjimky označujeme jako kontrolované (checked),
protože překladač kontroluje dodržení pravidel:
● Každá metoda, která může vyhodit kontrolovanou výjimku,
se musí k této skutečnosti veřejně přihlásit
● Každé použití metody, která může vyhodit kontrolovanou výjimku,
musí být buď uzavřeno v bloku try…catch,
nebo se volající metoda musí přihlásit k tomu,
že může také vyhodit danou kontrolovanou výjimku
► Nekontrolované výjimky ohlašují chyby v programu,
kontrolované výjimky očekávatelné situace,
na jejichž výskyt má být program připraven
a měl by na ně umět reagovat
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
17
Hierarchie výjimek
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
18
Pořadí výjimek v blocích catch
► Třída NumberFormatException
je potomkem třídy RuntimeException
try {
Syntaktická chyba,
......
na druhý blok catch nikdy nedojde
}
catch (RuntimeException e) {
.........
}
Obrácené pořadí bloků catch
catch (NumberFormatException e){
vše vyřeší
........
try {
}
......
}
catch (NumberFormatException e) {
.........
}
catch (RuntimeException e){
........
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
19
Metody generující výjimky
► Java vyžaduje, aby programy, které používají metody
schopné vyvolat kontrolované výjimky,
byly o této schopnosti používaných metod informovány =>
pak vědí, které výjimku musí umět zachytit a ošetřit
► Všechny kontrolované výjimky, které může metoda vyhodit,
musí deklarovat v hlavičce za klíčovým slovem throws
► Deklarace vyhazování nekontrolovaných výjimek není povinná
public void metoda()
throws KontrolovanáVýjimka1,
KontrolovanáVýjimka2
{
// Tělo metody
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
20
Metody třídy Throwable
► String getMessage()
Vrátí zprávu popisující danou výjimku
► String toString()
Vrátí název třídy výjimky následovaný případnou zprávou
► void printStackTrace()
Vytiskne toString() následovaný sadou informací o volající
posloupnosti, která vedla k vzniku výjimky
► Throwable fillInStackTrace()
Připraví nové informace o volací posloupnosti
vedoucí k místu zavolání této metody
► StackTraceElement[] getStackTrace()
Vrátí uchované informace o volací posloupnosti dané výjimky
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
21
Zřetězené výjimky
► V některých situacích je vhodné v rámci ošetření výjimky vyvolat
jinou výjimku, a přitom umožnit zjistit,
která výjimka byla prvotním hybatelem celé akce
► Řada výjimek má mezi svými konstruktory i takové,
které akceptují jako poslední parametr
odkaz na výjimku, jež byla příčinou vyvolání dané výjimky
► Chce-li se program zeptat výjimky na výjimku, která ji způsobila,
použije metodu
public Throwable getCause()
► Ve zprávě o vyvolání výjimky jsou místa, kde byla jedna výjimka
nahrazena jinou, označována textem caused by:
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
22
Ukázka výpisu při zřetězení výjimek
HighLevelException: MidLevelException: LowLevelException
at Junk.a(Junk.java:13)
at Junk.main(Junk.java:4)
Caused by: MidLevelException: LowLevelException
at Junk.c(Junk.java:23)
at Junk.b(Junk.java:17)
at Junk.a(Junk.java:11)
... 1 more
Caused by: LowLevelException
at Junk.e(Junk.java:30)
at Junk.d(Junk.java:27)
at Junk.c(Junk.java:21)
... 3 more
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
23
Převod kontrolovaných na nekontrolované
► Ošetřování kontrolovaných výjimek obtěžuje
► Víme-li, že k dané výjimce nejspíš nedojde
a ošetřujeme-li ji pouze proto, že na tom překladač trvá,
můžeme pro případ, že by k výjimce přece jenom došlo
zaměnit kontrolovanou výjimku za nekontrolovanou
public void prevod( String s ) {
try {
prověř( s );
} catch( Exception ex ) {
throw new RuntimeException( " Neprověřeno! ", ex );
}
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
24
Vaše jistota na trhu IT
Definice vlastních výjimek
►Hierarchie výjimek
►Pořadí výjimek v blocích catch
►Metody generující výjimky
►Metody třídy Throwable
►Vlastní výjimky
►Zásady správného používání výjimek
Definice vlastních výjimek
► Výjimky jsou zcela běžné třídy;
považujeme-li to proto za vhodné, můžeme definovat i vlastní
► Před definicí nové výjimky bychom si měli ujasnit,
bude-li kontrolovaná či nekontrolovaná;
podle toho definujeme jejího předka
► Název výjimek končí dle konvencí slovem Exception
před nímž je naznačena podstata dané výjimky
● IllegalArgumetnException
● NoSuchMethodException
● BadStringOperationException
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
26
Příklad vlastní kontrolované výjimky
public class VelkýPrůšvihException
extends Exception
{
public VelkýPrůšvihException() {};
public VelkýPrůšvihException( String zpráva ) {
super( zpráva );
}
public VelkýPrůšvihException(String zpráva,
Throwable původce ) {
super( zpráva, původce );
}
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
27
Test správného vyhození výjimky
► Na vytvářených programech je třeba otestovat i to,
že v definovaných situacích vyhodí požadovanou výjimku
public void testVyhozeníVýjimky()
{
try {
metodaKteráMáVyhoditVýjimku();
} catch ( VelkýPrůšvihException vpe ) {
return;
}
fail( "Nebyla vyhozena výjimka VelkýPrůšvihException" );
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
28
Zásady správného používání výjimek
1/2
Neignorujte
výjimky
try {
//Nějaký kód
}
catch(Exception e){}
► Výjimky, o nichž víte, že nemohou nastat,
převeďte na nekontrolované pro případ,
že by v budoucích verzích programu nastat mohly
► Při ošetřování výjimek, které nastat mohou,
ale nemají vliv na chod programu,
vložte do těla ošetření alespoň vysvětlující komentář
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
29
Zásady správného používání výjimek
2/2
► Používejte výjimky pouze k ošetření výjimečných stavů
► Kontrolované výjimky používejte u stavů, z nichž se lze zotavit,
jinak použijte výjimky nekontrolované
► Vyhýbejte se zbytečnému používání kontrolovaných výjimek
● Programátory ošetřování kontrolovaných výjimek obtěžuje
a mají pak tendenci je ošetřovat prázdným blokem catch
► Dávejte přednost standardním výjimkám,
vyvolávejte výjimky odpovídající dané abstrakci
● Programátoři by měli z názvu výjimky poznat, co se stalo
● Standardní výjimky mají všeobecně známý význam
► Snažte se o atomičnost selhání; i po vyhození výjimky
by měl být objekt v dobře definovaném stavu
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
30
Zásady správného používání výjimek
3/2
► Doplňujte výjimky zprávami,
výjimka by sama měla poskytnout dostatek informací
a neměla by programátora nutit k podrobnější analýze programu
► Dokumentujte vyvolávané výjimky v dokumentačních
komentářích pomocí značky @throws
► Nedělejte bloky try zbytečně velké,
kód uvnitř těchto bloků se neoptimalizuje
► Umíte-li výjimku v metodě ošetřit, udělejte to
► Detekuje-li se chyba v jedné metodě a má se ošetřit v jiné
(stejné či jiné instance), použijte výjimku.
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
31
Nejčastěji používané výjimky
1/2
► IllegalArgumentException
Byla zadána nepovolená hodnota parametru
● Např. chci nastavit zápornou velikost grafického tvaru
► IllegalStateException
V daném stavu objektu nelze metodu provést
● Např. otevřu soubor, přečtu pár vět, zavřu soubor a chci znovu přečíst větu
► NullPointerException
Byla vyvolána metoda instance, na níž ukazuje prázdný odkaz,
nebo byl předán nepovolený prázdný odkaz v parametru
► ArrayIndexOutOfBoundException
Byly zadány špatné meze pole, buď záporné nebo moc velké
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
32
Nejčastěji používané výjimky
2/2
► ConcurrentModificationException
V průběhu iterace byla změněna struktura kontejneru
● Např. byl do kontejneru přidán prvek
► NumberFormatException
Je požadován špatný převod řetězce na číslo či naopak
● Chci-li např. převést na číslo řetězec, který není číslem
● Častá chyba v metodách String.format či PrintStream.printf
► ClassCastException
Požadované přetypování není možné
► UnsupportedOperationException
Požadovaná operace není podporována
(např. chci přidat prvek do neměnného kontejneru)
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
33
Vaše jistota na trhu IT
Děkuji za pozornost
►Rudolf Pecinovský
http://vyuka.pecinovsky.cz/vse
mail: [email protected]
ICQ: 158 156 600
Slide 15
Vaše jistota na trhu IT
Výjimky
Rudolf Pecinovský
[email protected]
Vaše jistota na trhu IT
Obsah s odkazy
►Výjimky
►Výjimky kontrolované a nekontrolované
►Definice vlastních výjimek
Vaše jistota na trhu IT
Výjimky
►Výjimečné situace v programech
►Ošetření nestandardních situací v Javě
►Zpráva o výjimce
►Klíčová slova
►Činnost
►Vyvolání
Výjimečné situace v programech
► V každém programu je alespoň jedna chyba –
program na ni musí být připraven
► Starší programy
● Program vypsal chybové hlášení a ukončil činnost;
● V některých situacích (válcovací stolice, autopilot, …) nepřijatelné
● Funkce vrátí hodnotu signalizující chybu
● Programátor musí neustále testovat, co funkce vrací
● Knihovna měla pro tyto účely vyhrazenu speciální proměnnou,
do níž se v případě chyby zapsal její kód; nahlédnutím do proměnné
program zjistil kód poslední chyby
● Programátor musí neustále testovat, jaká je v proměnné hodnota
► Některé jazyky (Cobol, PL/1, …) proto přišly s koncepcí
ošetření nestandardních situací
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
4
Ošetření nestandardních situací v Javě
► Výjimečná událost =
problém, který brání dalšímu vykonávání části kódu
► Událost je výjimečná v tom, že na rozdíl od běžných problémů
nemá program k vyřešení situace dost informaci
► Program může při výskytu výjimečné události vyvolat výjimku
► Výjimka (exception)
objekt určený k přenosu informací o nastalém problému
z místa jeho vzniku do místa, kde bude problém řešen
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
5
Postup při vyvolání výjimky
1. Vytvoří se výjimka = objekt typu Throwable
(prakticky vždy instance některého z potomků)
2. Vytvořená výjimka se vyhodí =
přeruší se běh programu v místě, kde výjimka vznikla,
a začne se hledat místo, kde bude daná výjimka ošetřena
3. Ošetření výjimky (handler) by mělo uvést program do stavu,
v němž může jeho vykonávání pokračovat
► Výjimka „probublává“ programem z místa vyhození stále výše
a nenarazí-li cestou nikde na své ošetření,
zachytí ji virtuální stroj, který na standardní chybový výstup
vypíše zprávu o vzniku výjimky
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
6
Systémová zpráva o vzniku výjimky
Zpráva o vzniku výjimky spolu s názvem vlákna,
v němž k výjimce došlo (zde AWT-EventQueue-0)
Popis druhu výjimky (aritmetická výjimka dělení nulou)
Informace o místě, odkud byla volána metoda,
která vyvolala metodu, v níž došlo k vyhození výjimky
Informace o místě, odkud byla volána metoda,
v níž došlo k vyhození výjimky
Úplný název třídy včetně balíčku
Copyright © 2006, Rudolf Pecinovský
Název metody
VŠE – 05
Název souboru se
zdrojovým kódem
Číslo řádku zdrojáku,
kde došlo k výjimce
7
Klíčová slova související s výjimkami
► try (zkus)
Označuje blok kódu, v němž může dojít k výjimce
► throw (hoď)
Příkaz k vyhození výjimky;
musí být následován odkazem na existující instanci
► catch (chyť)
Blok ošetřující výjimku, která je zadána jako parametr
► finally (na konec)
Blok s povinnými závěrečnými akcemi nezávisejícími
na případném vzniku výjimky
► throws (hází)
Uvození seznamu výjimek vyhazovaných danou metodou
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
8
Vyvolání a ošetření výjimky v kódu
try {
//Kód, který může vyvolat výjimky
}
catch( Typ1 id1 ) {
//Ošetření výjimek typu Typ1
}
...
catch( TypN idN ) {
//ošetření výjimek typu TypN
}
finally {
//Kód, který se na závěr VŽDY provede
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
9
Náznak činnosti – řádný průběh
nedojde k vyvolání výjimky
= nedojde k chybě
try {
příkaz1();
příkaz2();
příkaz3();
}
catch ( xxxException e ) {
příkazProOšetřeníChyby();
}
Bloky catch
catch (…..
se přeskočí
finally {
ukončovacíPříkazy();
}
dalšíPříkaz();
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
12
Náznak činnosti – ošetřený výjimka
try {
příkaz1(); Při provádění metody příkaz2
dojde k ošetřené chybě
příkaz2();
příkaz3();
Byla vyhozena výjimka
tohoto typu nebo typu
}
některého z potomků
catch ( xxxException e ) {
příkazProOšetřeníChyby();
}
Ostatní bloky catch
catch (…..
se přeskočí
finally {
ukončovacíPříkazy();
}
dalšíPříkaz();
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
13
Náznak činnosti – neošetřená výjimka
Při provádění metody příkaz2
dojde k NEošetřené chybě
try {
příkaz1();
příkaz2();
příkaz3();
}
catch ( xxxException e ) {
příkazProOšetřeníChyby();
}
Ošetření nebylo nalezeno =>
catch (…..
provede se blok finally
a opouští se metoda
finally {
ukončovacíPříkazy();
}
dalšíPříkaz();
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
14
Vyvolání výjimky
public class Xyz implements Comparable
{
public bolean compareTo( Object o )
{
if( !(o instanceOf Xyz) )
throw new ClassCastException (
"\nPokus o porovnání s neporovnatelnou"
+ " instancí " + o );
//Zjištění, kdo je větší
return vysledek;
}
}
► Instanci nemusíme vytvářet až v příkazu throw,
můžeme ji vytvořit kdykoliv před tím a pak mu ji jen předat
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
15
Vaše jistota na trhu IT
Výjimky kontrolované a
nekontrolované
►Hierarchie výjimek
►Pořadí výjimek v blocích catch
►Metody generující výjimky
►Metody třídy Throwable
►Zřetězené výjimky
►Převod kontrolovaných na nekontrolované
Charakteristika
► Výjimky, které jsou potomky třídy RuntimeException
nebo Error označujeme jako nekontrolované (unchecked),
protože překladač nekontroluje, zda je na ně program připraven
► Ostatní výjimky označujeme jako kontrolované (checked),
protože překladač kontroluje dodržení pravidel:
● Každá metoda, která může vyhodit kontrolovanou výjimku,
se musí k této skutečnosti veřejně přihlásit
● Každé použití metody, která může vyhodit kontrolovanou výjimku,
musí být buď uzavřeno v bloku try…catch,
nebo se volající metoda musí přihlásit k tomu,
že může také vyhodit danou kontrolovanou výjimku
► Nekontrolované výjimky ohlašují chyby v programu,
kontrolované výjimky očekávatelné situace,
na jejichž výskyt má být program připraven
a měl by na ně umět reagovat
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
17
Hierarchie výjimek
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
18
Pořadí výjimek v blocích catch
► Třída NumberFormatException
je potomkem třídy RuntimeException
try {
Syntaktická chyba,
......
na druhý blok catch nikdy nedojde
}
catch (RuntimeException e) {
.........
}
Obrácené pořadí bloků catch
catch (NumberFormatException e){
vše vyřeší
........
try {
}
......
}
catch (NumberFormatException e) {
.........
}
catch (RuntimeException e){
........
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
19
Metody generující výjimky
► Java vyžaduje, aby programy, které používají metody
schopné vyvolat kontrolované výjimky,
byly o této schopnosti používaných metod informovány =>
pak vědí, které výjimku musí umět zachytit a ošetřit
► Všechny kontrolované výjimky, které může metoda vyhodit,
musí deklarovat v hlavičce za klíčovým slovem throws
► Deklarace vyhazování nekontrolovaných výjimek není povinná
public void metoda()
throws KontrolovanáVýjimka1,
KontrolovanáVýjimka2
{
// Tělo metody
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
20
Metody třídy Throwable
► String getMessage()
Vrátí zprávu popisující danou výjimku
► String toString()
Vrátí název třídy výjimky následovaný případnou zprávou
► void printStackTrace()
Vytiskne toString() následovaný sadou informací o volající
posloupnosti, která vedla k vzniku výjimky
► Throwable fillInStackTrace()
Připraví nové informace o volací posloupnosti
vedoucí k místu zavolání této metody
► StackTraceElement[] getStackTrace()
Vrátí uchované informace o volací posloupnosti dané výjimky
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
21
Zřetězené výjimky
► V některých situacích je vhodné v rámci ošetření výjimky vyvolat
jinou výjimku, a přitom umožnit zjistit,
která výjimka byla prvotním hybatelem celé akce
► Řada výjimek má mezi svými konstruktory i takové,
které akceptují jako poslední parametr
odkaz na výjimku, jež byla příčinou vyvolání dané výjimky
► Chce-li se program zeptat výjimky na výjimku, která ji způsobila,
použije metodu
public Throwable getCause()
► Ve zprávě o vyvolání výjimky jsou místa, kde byla jedna výjimka
nahrazena jinou, označována textem caused by:
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
22
Ukázka výpisu při zřetězení výjimek
HighLevelException: MidLevelException: LowLevelException
at Junk.a(Junk.java:13)
at Junk.main(Junk.java:4)
Caused by: MidLevelException: LowLevelException
at Junk.c(Junk.java:23)
at Junk.b(Junk.java:17)
at Junk.a(Junk.java:11)
... 1 more
Caused by: LowLevelException
at Junk.e(Junk.java:30)
at Junk.d(Junk.java:27)
at Junk.c(Junk.java:21)
... 3 more
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
23
Převod kontrolovaných na nekontrolované
► Ošetřování kontrolovaných výjimek obtěžuje
► Víme-li, že k dané výjimce nejspíš nedojde
a ošetřujeme-li ji pouze proto, že na tom překladač trvá,
můžeme pro případ, že by k výjimce přece jenom došlo
zaměnit kontrolovanou výjimku za nekontrolovanou
public void prevod( String s ) {
try {
prověř( s );
} catch( Exception ex ) {
throw new RuntimeException( " Neprověřeno! ", ex );
}
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
24
Vaše jistota na trhu IT
Definice vlastních výjimek
►Hierarchie výjimek
►Pořadí výjimek v blocích catch
►Metody generující výjimky
►Metody třídy Throwable
►Vlastní výjimky
►Zásady správného používání výjimek
Definice vlastních výjimek
► Výjimky jsou zcela běžné třídy;
považujeme-li to proto za vhodné, můžeme definovat i vlastní
► Před definicí nové výjimky bychom si měli ujasnit,
bude-li kontrolovaná či nekontrolovaná;
podle toho definujeme jejího předka
► Název výjimek končí dle konvencí slovem Exception
před nímž je naznačena podstata dané výjimky
● IllegalArgumetnException
● NoSuchMethodException
● BadStringOperationException
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
26
Příklad vlastní kontrolované výjimky
public class VelkýPrůšvihException
extends Exception
{
public VelkýPrůšvihException() {};
public VelkýPrůšvihException( String zpráva ) {
super( zpráva );
}
public VelkýPrůšvihException(String zpráva,
Throwable původce ) {
super( zpráva, původce );
}
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
27
Test správného vyhození výjimky
► Na vytvářených programech je třeba otestovat i to,
že v definovaných situacích vyhodí požadovanou výjimku
public void testVyhozeníVýjimky()
{
try {
metodaKteráMáVyhoditVýjimku();
} catch ( VelkýPrůšvihException vpe ) {
return;
}
fail( "Nebyla vyhozena výjimka VelkýPrůšvihException" );
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
28
Zásady správného používání výjimek
1/2
Neignorujte
výjimky
try {
//Nějaký kód
}
catch(Exception e){}
► Výjimky, o nichž víte, že nemohou nastat,
převeďte na nekontrolované pro případ,
že by v budoucích verzích programu nastat mohly
► Při ošetřování výjimek, které nastat mohou,
ale nemají vliv na chod programu,
vložte do těla ošetření alespoň vysvětlující komentář
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
29
Zásady správného používání výjimek
2/2
► Používejte výjimky pouze k ošetření výjimečných stavů
► Kontrolované výjimky používejte u stavů, z nichž se lze zotavit,
jinak použijte výjimky nekontrolované
► Vyhýbejte se zbytečnému používání kontrolovaných výjimek
● Programátory ošetřování kontrolovaných výjimek obtěžuje
a mají pak tendenci je ošetřovat prázdným blokem catch
► Dávejte přednost standardním výjimkám,
vyvolávejte výjimky odpovídající dané abstrakci
● Programátoři by měli z názvu výjimky poznat, co se stalo
● Standardní výjimky mají všeobecně známý význam
► Snažte se o atomičnost selhání; i po vyhození výjimky
by měl být objekt v dobře definovaném stavu
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
30
Zásady správného používání výjimek
3/2
► Doplňujte výjimky zprávami,
výjimka by sama měla poskytnout dostatek informací
a neměla by programátora nutit k podrobnější analýze programu
► Dokumentujte vyvolávané výjimky v dokumentačních
komentářích pomocí značky @throws
► Nedělejte bloky try zbytečně velké,
kód uvnitř těchto bloků se neoptimalizuje
► Umíte-li výjimku v metodě ošetřit, udělejte to
► Detekuje-li se chyba v jedné metodě a má se ošetřit v jiné
(stejné či jiné instance), použijte výjimku.
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
31
Nejčastěji používané výjimky
1/2
► IllegalArgumentException
Byla zadána nepovolená hodnota parametru
● Např. chci nastavit zápornou velikost grafického tvaru
► IllegalStateException
V daném stavu objektu nelze metodu provést
● Např. otevřu soubor, přečtu pár vět, zavřu soubor a chci znovu přečíst větu
► NullPointerException
Byla vyvolána metoda instance, na níž ukazuje prázdný odkaz,
nebo byl předán nepovolený prázdný odkaz v parametru
► ArrayIndexOutOfBoundException
Byly zadány špatné meze pole, buď záporné nebo moc velké
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
32
Nejčastěji používané výjimky
2/2
► ConcurrentModificationException
V průběhu iterace byla změněna struktura kontejneru
● Např. byl do kontejneru přidán prvek
► NumberFormatException
Je požadován špatný převod řetězce na číslo či naopak
● Chci-li např. převést na číslo řetězec, který není číslem
● Častá chyba v metodách String.format či PrintStream.printf
► ClassCastException
Požadované přetypování není možné
► UnsupportedOperationException
Požadovaná operace není podporována
(např. chci přidat prvek do neměnného kontejneru)
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
33
Vaše jistota na trhu IT
Děkuji za pozornost
►Rudolf Pecinovský
http://vyuka.pecinovsky.cz/vse
mail: [email protected]
ICQ: 158 156 600
Slide 16
Vaše jistota na trhu IT
Výjimky
Rudolf Pecinovský
[email protected]
Vaše jistota na trhu IT
Obsah s odkazy
►Výjimky
►Výjimky kontrolované a nekontrolované
►Definice vlastních výjimek
Vaše jistota na trhu IT
Výjimky
►Výjimečné situace v programech
►Ošetření nestandardních situací v Javě
►Zpráva o výjimce
►Klíčová slova
►Činnost
►Vyvolání
Výjimečné situace v programech
► V každém programu je alespoň jedna chyba –
program na ni musí být připraven
► Starší programy
● Program vypsal chybové hlášení a ukončil činnost;
● V některých situacích (válcovací stolice, autopilot, …) nepřijatelné
● Funkce vrátí hodnotu signalizující chybu
● Programátor musí neustále testovat, co funkce vrací
● Knihovna měla pro tyto účely vyhrazenu speciální proměnnou,
do níž se v případě chyby zapsal její kód; nahlédnutím do proměnné
program zjistil kód poslední chyby
● Programátor musí neustále testovat, jaká je v proměnné hodnota
► Některé jazyky (Cobol, PL/1, …) proto přišly s koncepcí
ošetření nestandardních situací
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
4
Ošetření nestandardních situací v Javě
► Výjimečná událost =
problém, který brání dalšímu vykonávání části kódu
► Událost je výjimečná v tom, že na rozdíl od běžných problémů
nemá program k vyřešení situace dost informaci
► Program může při výskytu výjimečné události vyvolat výjimku
► Výjimka (exception)
objekt určený k přenosu informací o nastalém problému
z místa jeho vzniku do místa, kde bude problém řešen
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
5
Postup při vyvolání výjimky
1. Vytvoří se výjimka = objekt typu Throwable
(prakticky vždy instance některého z potomků)
2. Vytvořená výjimka se vyhodí =
přeruší se běh programu v místě, kde výjimka vznikla,
a začne se hledat místo, kde bude daná výjimka ošetřena
3. Ošetření výjimky (handler) by mělo uvést program do stavu,
v němž může jeho vykonávání pokračovat
► Výjimka „probublává“ programem z místa vyhození stále výše
a nenarazí-li cestou nikde na své ošetření,
zachytí ji virtuální stroj, který na standardní chybový výstup
vypíše zprávu o vzniku výjimky
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
6
Systémová zpráva o vzniku výjimky
Zpráva o vzniku výjimky spolu s názvem vlákna,
v němž k výjimce došlo (zde AWT-EventQueue-0)
Popis druhu výjimky (aritmetická výjimka dělení nulou)
Informace o místě, odkud byla volána metoda,
která vyvolala metodu, v níž došlo k vyhození výjimky
Informace o místě, odkud byla volána metoda,
v níž došlo k vyhození výjimky
Úplný název třídy včetně balíčku
Copyright © 2006, Rudolf Pecinovský
Název metody
VŠE – 05
Název souboru se
zdrojovým kódem
Číslo řádku zdrojáku,
kde došlo k výjimce
7
Klíčová slova související s výjimkami
► try (zkus)
Označuje blok kódu, v němž může dojít k výjimce
► throw (hoď)
Příkaz k vyhození výjimky;
musí být následován odkazem na existující instanci
► catch (chyť)
Blok ošetřující výjimku, která je zadána jako parametr
► finally (na konec)
Blok s povinnými závěrečnými akcemi nezávisejícími
na případném vzniku výjimky
► throws (hází)
Uvození seznamu výjimek vyhazovaných danou metodou
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
8
Vyvolání a ošetření výjimky v kódu
try {
//Kód, který může vyvolat výjimky
}
catch( Typ1 id1 ) {
//Ošetření výjimek typu Typ1
}
...
catch( TypN idN ) {
//ošetření výjimek typu TypN
}
finally {
//Kód, který se na závěr VŽDY provede
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
9
Náznak činnosti – řádný průběh
nedojde k vyvolání výjimky
= nedojde k chybě
try {
příkaz1();
příkaz2();
příkaz3();
}
catch ( xxxException e ) {
příkazProOšetřeníChyby();
}
Bloky catch
catch (…..
se přeskočí
finally {
ukončovacíPříkazy();
}
dalšíPříkaz();
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
12
Náznak činnosti – ošetřený výjimka
try {
příkaz1(); Při provádění metody příkaz2
dojde k ošetřené chybě
příkaz2();
příkaz3();
Byla vyhozena výjimka
tohoto typu nebo typu
}
některého z potomků
catch ( xxxException e ) {
příkazProOšetřeníChyby();
}
Ostatní bloky catch
catch (…..
se přeskočí
finally {
ukončovacíPříkazy();
}
dalšíPříkaz();
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
13
Náznak činnosti – neošetřená výjimka
Při provádění metody příkaz2
dojde k NEošetřené chybě
try {
příkaz1();
příkaz2();
příkaz3();
}
catch ( xxxException e ) {
příkazProOšetřeníChyby();
}
Ošetření nebylo nalezeno =>
catch (…..
provede se blok finally
a opouští se metoda
finally {
ukončovacíPříkazy();
}
dalšíPříkaz();
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
14
Vyvolání výjimky
public class Xyz implements Comparable
{
public bolean compareTo( Object o )
{
if( !(o instanceOf Xyz) )
throw new ClassCastException (
"\nPokus o porovnání s neporovnatelnou"
+ " instancí " + o );
//Zjištění, kdo je větší
return vysledek;
}
}
► Instanci nemusíme vytvářet až v příkazu throw,
můžeme ji vytvořit kdykoliv před tím a pak mu ji jen předat
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
15
Vaše jistota na trhu IT
Výjimky kontrolované a
nekontrolované
►Hierarchie výjimek
►Pořadí výjimek v blocích catch
►Metody generující výjimky
►Metody třídy Throwable
►Zřetězené výjimky
►Převod kontrolovaných na nekontrolované
Charakteristika
► Výjimky, které jsou potomky třídy RuntimeException
nebo Error označujeme jako nekontrolované (unchecked),
protože překladač nekontroluje, zda je na ně program připraven
► Ostatní výjimky označujeme jako kontrolované (checked),
protože překladač kontroluje dodržení pravidel:
● Každá metoda, která může vyhodit kontrolovanou výjimku,
se musí k této skutečnosti veřejně přihlásit
● Každé použití metody, která může vyhodit kontrolovanou výjimku,
musí být buď uzavřeno v bloku try…catch,
nebo se volající metoda musí přihlásit k tomu,
že může také vyhodit danou kontrolovanou výjimku
► Nekontrolované výjimky ohlašují chyby v programu,
kontrolované výjimky očekávatelné situace,
na jejichž výskyt má být program připraven
a měl by na ně umět reagovat
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
17
Hierarchie výjimek
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
18
Pořadí výjimek v blocích catch
► Třída NumberFormatException
je potomkem třídy RuntimeException
try {
Syntaktická chyba,
......
na druhý blok catch nikdy nedojde
}
catch (RuntimeException e) {
.........
}
Obrácené pořadí bloků catch
catch (NumberFormatException e){
vše vyřeší
........
try {
}
......
}
catch (NumberFormatException e) {
.........
}
catch (RuntimeException e){
........
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
19
Metody generující výjimky
► Java vyžaduje, aby programy, které používají metody
schopné vyvolat kontrolované výjimky,
byly o této schopnosti používaných metod informovány =>
pak vědí, které výjimku musí umět zachytit a ošetřit
► Všechny kontrolované výjimky, které může metoda vyhodit,
musí deklarovat v hlavičce za klíčovým slovem throws
► Deklarace vyhazování nekontrolovaných výjimek není povinná
public void metoda()
throws KontrolovanáVýjimka1,
KontrolovanáVýjimka2
{
// Tělo metody
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
20
Metody třídy Throwable
► String getMessage()
Vrátí zprávu popisující danou výjimku
► String toString()
Vrátí název třídy výjimky následovaný případnou zprávou
► void printStackTrace()
Vytiskne toString() následovaný sadou informací o volající
posloupnosti, která vedla k vzniku výjimky
► Throwable fillInStackTrace()
Připraví nové informace o volací posloupnosti
vedoucí k místu zavolání této metody
► StackTraceElement[] getStackTrace()
Vrátí uchované informace o volací posloupnosti dané výjimky
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
21
Zřetězené výjimky
► V některých situacích je vhodné v rámci ošetření výjimky vyvolat
jinou výjimku, a přitom umožnit zjistit,
která výjimka byla prvotním hybatelem celé akce
► Řada výjimek má mezi svými konstruktory i takové,
které akceptují jako poslední parametr
odkaz na výjimku, jež byla příčinou vyvolání dané výjimky
► Chce-li se program zeptat výjimky na výjimku, která ji způsobila,
použije metodu
public Throwable getCause()
► Ve zprávě o vyvolání výjimky jsou místa, kde byla jedna výjimka
nahrazena jinou, označována textem caused by:
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
22
Ukázka výpisu při zřetězení výjimek
HighLevelException: MidLevelException: LowLevelException
at Junk.a(Junk.java:13)
at Junk.main(Junk.java:4)
Caused by: MidLevelException: LowLevelException
at Junk.c(Junk.java:23)
at Junk.b(Junk.java:17)
at Junk.a(Junk.java:11)
... 1 more
Caused by: LowLevelException
at Junk.e(Junk.java:30)
at Junk.d(Junk.java:27)
at Junk.c(Junk.java:21)
... 3 more
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
23
Převod kontrolovaných na nekontrolované
► Ošetřování kontrolovaných výjimek obtěžuje
► Víme-li, že k dané výjimce nejspíš nedojde
a ošetřujeme-li ji pouze proto, že na tom překladač trvá,
můžeme pro případ, že by k výjimce přece jenom došlo
zaměnit kontrolovanou výjimku za nekontrolovanou
public void prevod( String s ) {
try {
prověř( s );
} catch( Exception ex ) {
throw new RuntimeException( " Neprověřeno! ", ex );
}
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
24
Vaše jistota na trhu IT
Definice vlastních výjimek
►Hierarchie výjimek
►Pořadí výjimek v blocích catch
►Metody generující výjimky
►Metody třídy Throwable
►Vlastní výjimky
►Zásady správného používání výjimek
Definice vlastních výjimek
► Výjimky jsou zcela běžné třídy;
považujeme-li to proto za vhodné, můžeme definovat i vlastní
► Před definicí nové výjimky bychom si měli ujasnit,
bude-li kontrolovaná či nekontrolovaná;
podle toho definujeme jejího předka
► Název výjimek končí dle konvencí slovem Exception
před nímž je naznačena podstata dané výjimky
● IllegalArgumetnException
● NoSuchMethodException
● BadStringOperationException
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
26
Příklad vlastní kontrolované výjimky
public class VelkýPrůšvihException
extends Exception
{
public VelkýPrůšvihException() {};
public VelkýPrůšvihException( String zpráva ) {
super( zpráva );
}
public VelkýPrůšvihException(String zpráva,
Throwable původce ) {
super( zpráva, původce );
}
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
27
Test správného vyhození výjimky
► Na vytvářených programech je třeba otestovat i to,
že v definovaných situacích vyhodí požadovanou výjimku
public void testVyhozeníVýjimky()
{
try {
metodaKteráMáVyhoditVýjimku();
} catch ( VelkýPrůšvihException vpe ) {
return;
}
fail( "Nebyla vyhozena výjimka VelkýPrůšvihException" );
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
28
Zásady správného používání výjimek
1/2
Neignorujte
výjimky
try {
//Nějaký kód
}
catch(Exception e){}
► Výjimky, o nichž víte, že nemohou nastat,
převeďte na nekontrolované pro případ,
že by v budoucích verzích programu nastat mohly
► Při ošetřování výjimek, které nastat mohou,
ale nemají vliv na chod programu,
vložte do těla ošetření alespoň vysvětlující komentář
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
29
Zásady správného používání výjimek
2/2
► Používejte výjimky pouze k ošetření výjimečných stavů
► Kontrolované výjimky používejte u stavů, z nichž se lze zotavit,
jinak použijte výjimky nekontrolované
► Vyhýbejte se zbytečnému používání kontrolovaných výjimek
● Programátory ošetřování kontrolovaných výjimek obtěžuje
a mají pak tendenci je ošetřovat prázdným blokem catch
► Dávejte přednost standardním výjimkám,
vyvolávejte výjimky odpovídající dané abstrakci
● Programátoři by měli z názvu výjimky poznat, co se stalo
● Standardní výjimky mají všeobecně známý význam
► Snažte se o atomičnost selhání; i po vyhození výjimky
by měl být objekt v dobře definovaném stavu
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
30
Zásady správného používání výjimek
3/2
► Doplňujte výjimky zprávami,
výjimka by sama měla poskytnout dostatek informací
a neměla by programátora nutit k podrobnější analýze programu
► Dokumentujte vyvolávané výjimky v dokumentačních
komentářích pomocí značky @throws
► Nedělejte bloky try zbytečně velké,
kód uvnitř těchto bloků se neoptimalizuje
► Umíte-li výjimku v metodě ošetřit, udělejte to
► Detekuje-li se chyba v jedné metodě a má se ošetřit v jiné
(stejné či jiné instance), použijte výjimku.
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
31
Nejčastěji používané výjimky
1/2
► IllegalArgumentException
Byla zadána nepovolená hodnota parametru
● Např. chci nastavit zápornou velikost grafického tvaru
► IllegalStateException
V daném stavu objektu nelze metodu provést
● Např. otevřu soubor, přečtu pár vět, zavřu soubor a chci znovu přečíst větu
► NullPointerException
Byla vyvolána metoda instance, na níž ukazuje prázdný odkaz,
nebo byl předán nepovolený prázdný odkaz v parametru
► ArrayIndexOutOfBoundException
Byly zadány špatné meze pole, buď záporné nebo moc velké
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
32
Nejčastěji používané výjimky
2/2
► ConcurrentModificationException
V průběhu iterace byla změněna struktura kontejneru
● Např. byl do kontejneru přidán prvek
► NumberFormatException
Je požadován špatný převod řetězce na číslo či naopak
● Chci-li např. převést na číslo řetězec, který není číslem
● Častá chyba v metodách String.format či PrintStream.printf
► ClassCastException
Požadované přetypování není možné
► UnsupportedOperationException
Požadovaná operace není podporována
(např. chci přidat prvek do neměnného kontejneru)
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
33
Vaše jistota na trhu IT
Děkuji za pozornost
►Rudolf Pecinovský
http://vyuka.pecinovsky.cz/vse
mail: [email protected]
ICQ: 158 156 600
Slide 17
Vaše jistota na trhu IT
Výjimky
Rudolf Pecinovský
[email protected]
Vaše jistota na trhu IT
Obsah s odkazy
►Výjimky
►Výjimky kontrolované a nekontrolované
►Definice vlastních výjimek
Vaše jistota na trhu IT
Výjimky
►Výjimečné situace v programech
►Ošetření nestandardních situací v Javě
►Zpráva o výjimce
►Klíčová slova
►Činnost
►Vyvolání
Výjimečné situace v programech
► V každém programu je alespoň jedna chyba –
program na ni musí být připraven
► Starší programy
● Program vypsal chybové hlášení a ukončil činnost;
● V některých situacích (válcovací stolice, autopilot, …) nepřijatelné
● Funkce vrátí hodnotu signalizující chybu
● Programátor musí neustále testovat, co funkce vrací
● Knihovna měla pro tyto účely vyhrazenu speciální proměnnou,
do níž se v případě chyby zapsal její kód; nahlédnutím do proměnné
program zjistil kód poslední chyby
● Programátor musí neustále testovat, jaká je v proměnné hodnota
► Některé jazyky (Cobol, PL/1, …) proto přišly s koncepcí
ošetření nestandardních situací
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
4
Ošetření nestandardních situací v Javě
► Výjimečná událost =
problém, který brání dalšímu vykonávání části kódu
► Událost je výjimečná v tom, že na rozdíl od běžných problémů
nemá program k vyřešení situace dost informaci
► Program může při výskytu výjimečné události vyvolat výjimku
► Výjimka (exception)
objekt určený k přenosu informací o nastalém problému
z místa jeho vzniku do místa, kde bude problém řešen
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
5
Postup při vyvolání výjimky
1. Vytvoří se výjimka = objekt typu Throwable
(prakticky vždy instance některého z potomků)
2. Vytvořená výjimka se vyhodí =
přeruší se běh programu v místě, kde výjimka vznikla,
a začne se hledat místo, kde bude daná výjimka ošetřena
3. Ošetření výjimky (handler) by mělo uvést program do stavu,
v němž může jeho vykonávání pokračovat
► Výjimka „probublává“ programem z místa vyhození stále výše
a nenarazí-li cestou nikde na své ošetření,
zachytí ji virtuální stroj, který na standardní chybový výstup
vypíše zprávu o vzniku výjimky
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
6
Systémová zpráva o vzniku výjimky
Zpráva o vzniku výjimky spolu s názvem vlákna,
v němž k výjimce došlo (zde AWT-EventQueue-0)
Popis druhu výjimky (aritmetická výjimka dělení nulou)
Informace o místě, odkud byla volána metoda,
která vyvolala metodu, v níž došlo k vyhození výjimky
Informace o místě, odkud byla volána metoda,
v níž došlo k vyhození výjimky
Úplný název třídy včetně balíčku
Copyright © 2006, Rudolf Pecinovský
Název metody
VŠE – 05
Název souboru se
zdrojovým kódem
Číslo řádku zdrojáku,
kde došlo k výjimce
7
Klíčová slova související s výjimkami
► try (zkus)
Označuje blok kódu, v němž může dojít k výjimce
► throw (hoď)
Příkaz k vyhození výjimky;
musí být následován odkazem na existující instanci
► catch (chyť)
Blok ošetřující výjimku, která je zadána jako parametr
► finally (na konec)
Blok s povinnými závěrečnými akcemi nezávisejícími
na případném vzniku výjimky
► throws (hází)
Uvození seznamu výjimek vyhazovaných danou metodou
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
8
Vyvolání a ošetření výjimky v kódu
try {
//Kód, který může vyvolat výjimky
}
catch( Typ1 id1 ) {
//Ošetření výjimek typu Typ1
}
...
catch( TypN idN ) {
//ošetření výjimek typu TypN
}
finally {
//Kód, který se na závěr VŽDY provede
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
9
Náznak činnosti – řádný průběh
nedojde k vyvolání výjimky
= nedojde k chybě
try {
příkaz1();
příkaz2();
příkaz3();
}
catch ( xxxException e ) {
příkazProOšetřeníChyby();
}
Bloky catch
catch (…..
se přeskočí
finally {
ukončovacíPříkazy();
}
dalšíPříkaz();
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
12
Náznak činnosti – ošetřený výjimka
try {
příkaz1(); Při provádění metody příkaz2
dojde k ošetřené chybě
příkaz2();
příkaz3();
Byla vyhozena výjimka
tohoto typu nebo typu
}
některého z potomků
catch ( xxxException e ) {
příkazProOšetřeníChyby();
}
Ostatní bloky catch
catch (…..
se přeskočí
finally {
ukončovacíPříkazy();
}
dalšíPříkaz();
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
13
Náznak činnosti – neošetřená výjimka
Při provádění metody příkaz2
dojde k NEošetřené chybě
try {
příkaz1();
příkaz2();
příkaz3();
}
catch ( xxxException e ) {
příkazProOšetřeníChyby();
}
Ošetření nebylo nalezeno =>
catch (…..
provede se blok finally
a opouští se metoda
finally {
ukončovacíPříkazy();
}
dalšíPříkaz();
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
14
Vyvolání výjimky
public class Xyz implements Comparable
{
public bolean compareTo( Object o )
{
if( !(o instanceOf Xyz) )
throw new ClassCastException (
"\nPokus o porovnání s neporovnatelnou"
+ " instancí " + o );
//Zjištění, kdo je větší
return vysledek;
}
}
► Instanci nemusíme vytvářet až v příkazu throw,
můžeme ji vytvořit kdykoliv před tím a pak mu ji jen předat
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
15
Vaše jistota na trhu IT
Výjimky kontrolované a
nekontrolované
►Hierarchie výjimek
►Pořadí výjimek v blocích catch
►Metody generující výjimky
►Metody třídy Throwable
►Zřetězené výjimky
►Převod kontrolovaných na nekontrolované
Charakteristika
► Výjimky, které jsou potomky třídy RuntimeException
nebo Error označujeme jako nekontrolované (unchecked),
protože překladač nekontroluje, zda je na ně program připraven
► Ostatní výjimky označujeme jako kontrolované (checked),
protože překladač kontroluje dodržení pravidel:
● Každá metoda, která může vyhodit kontrolovanou výjimku,
se musí k této skutečnosti veřejně přihlásit
● Každé použití metody, která může vyhodit kontrolovanou výjimku,
musí být buď uzavřeno v bloku try…catch,
nebo se volající metoda musí přihlásit k tomu,
že může také vyhodit danou kontrolovanou výjimku
► Nekontrolované výjimky ohlašují chyby v programu,
kontrolované výjimky očekávatelné situace,
na jejichž výskyt má být program připraven
a měl by na ně umět reagovat
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
17
Hierarchie výjimek
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
18
Pořadí výjimek v blocích catch
► Třída NumberFormatException
je potomkem třídy RuntimeException
try {
Syntaktická chyba,
......
na druhý blok catch nikdy nedojde
}
catch (RuntimeException e) {
.........
}
Obrácené pořadí bloků catch
catch (NumberFormatException e){
vše vyřeší
........
try {
}
......
}
catch (NumberFormatException e) {
.........
}
catch (RuntimeException e){
........
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
19
Metody generující výjimky
► Java vyžaduje, aby programy, které používají metody
schopné vyvolat kontrolované výjimky,
byly o této schopnosti používaných metod informovány =>
pak vědí, které výjimku musí umět zachytit a ošetřit
► Všechny kontrolované výjimky, které může metoda vyhodit,
musí deklarovat v hlavičce za klíčovým slovem throws
► Deklarace vyhazování nekontrolovaných výjimek není povinná
public void metoda()
throws KontrolovanáVýjimka1,
KontrolovanáVýjimka2
{
// Tělo metody
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
20
Metody třídy Throwable
► String getMessage()
Vrátí zprávu popisující danou výjimku
► String toString()
Vrátí název třídy výjimky následovaný případnou zprávou
► void printStackTrace()
Vytiskne toString() následovaný sadou informací o volající
posloupnosti, která vedla k vzniku výjimky
► Throwable fillInStackTrace()
Připraví nové informace o volací posloupnosti
vedoucí k místu zavolání této metody
► StackTraceElement[] getStackTrace()
Vrátí uchované informace o volací posloupnosti dané výjimky
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
21
Zřetězené výjimky
► V některých situacích je vhodné v rámci ošetření výjimky vyvolat
jinou výjimku, a přitom umožnit zjistit,
která výjimka byla prvotním hybatelem celé akce
► Řada výjimek má mezi svými konstruktory i takové,
které akceptují jako poslední parametr
odkaz na výjimku, jež byla příčinou vyvolání dané výjimky
► Chce-li se program zeptat výjimky na výjimku, která ji způsobila,
použije metodu
public Throwable getCause()
► Ve zprávě o vyvolání výjimky jsou místa, kde byla jedna výjimka
nahrazena jinou, označována textem caused by:
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
22
Ukázka výpisu při zřetězení výjimek
HighLevelException: MidLevelException: LowLevelException
at Junk.a(Junk.java:13)
at Junk.main(Junk.java:4)
Caused by: MidLevelException: LowLevelException
at Junk.c(Junk.java:23)
at Junk.b(Junk.java:17)
at Junk.a(Junk.java:11)
... 1 more
Caused by: LowLevelException
at Junk.e(Junk.java:30)
at Junk.d(Junk.java:27)
at Junk.c(Junk.java:21)
... 3 more
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
23
Převod kontrolovaných na nekontrolované
► Ošetřování kontrolovaných výjimek obtěžuje
► Víme-li, že k dané výjimce nejspíš nedojde
a ošetřujeme-li ji pouze proto, že na tom překladač trvá,
můžeme pro případ, že by k výjimce přece jenom došlo
zaměnit kontrolovanou výjimku za nekontrolovanou
public void prevod( String s ) {
try {
prověř( s );
} catch( Exception ex ) {
throw new RuntimeException( " Neprověřeno! ", ex );
}
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
24
Vaše jistota na trhu IT
Definice vlastních výjimek
►Hierarchie výjimek
►Pořadí výjimek v blocích catch
►Metody generující výjimky
►Metody třídy Throwable
►Vlastní výjimky
►Zásady správného používání výjimek
Definice vlastních výjimek
► Výjimky jsou zcela běžné třídy;
považujeme-li to proto za vhodné, můžeme definovat i vlastní
► Před definicí nové výjimky bychom si měli ujasnit,
bude-li kontrolovaná či nekontrolovaná;
podle toho definujeme jejího předka
► Název výjimek končí dle konvencí slovem Exception
před nímž je naznačena podstata dané výjimky
● IllegalArgumetnException
● NoSuchMethodException
● BadStringOperationException
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
26
Příklad vlastní kontrolované výjimky
public class VelkýPrůšvihException
extends Exception
{
public VelkýPrůšvihException() {};
public VelkýPrůšvihException( String zpráva ) {
super( zpráva );
}
public VelkýPrůšvihException(String zpráva,
Throwable původce ) {
super( zpráva, původce );
}
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
27
Test správného vyhození výjimky
► Na vytvářených programech je třeba otestovat i to,
že v definovaných situacích vyhodí požadovanou výjimku
public void testVyhozeníVýjimky()
{
try {
metodaKteráMáVyhoditVýjimku();
} catch ( VelkýPrůšvihException vpe ) {
return;
}
fail( "Nebyla vyhozena výjimka VelkýPrůšvihException" );
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
28
Zásady správného používání výjimek
1/2
Neignorujte
výjimky
try {
//Nějaký kód
}
catch(Exception e){}
► Výjimky, o nichž víte, že nemohou nastat,
převeďte na nekontrolované pro případ,
že by v budoucích verzích programu nastat mohly
► Při ošetřování výjimek, které nastat mohou,
ale nemají vliv na chod programu,
vložte do těla ošetření alespoň vysvětlující komentář
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
29
Zásady správného používání výjimek
2/2
► Používejte výjimky pouze k ošetření výjimečných stavů
► Kontrolované výjimky používejte u stavů, z nichž se lze zotavit,
jinak použijte výjimky nekontrolované
► Vyhýbejte se zbytečnému používání kontrolovaných výjimek
● Programátory ošetřování kontrolovaných výjimek obtěžuje
a mají pak tendenci je ošetřovat prázdným blokem catch
► Dávejte přednost standardním výjimkám,
vyvolávejte výjimky odpovídající dané abstrakci
● Programátoři by měli z názvu výjimky poznat, co se stalo
● Standardní výjimky mají všeobecně známý význam
► Snažte se o atomičnost selhání; i po vyhození výjimky
by měl být objekt v dobře definovaném stavu
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
30
Zásady správného používání výjimek
3/2
► Doplňujte výjimky zprávami,
výjimka by sama měla poskytnout dostatek informací
a neměla by programátora nutit k podrobnější analýze programu
► Dokumentujte vyvolávané výjimky v dokumentačních
komentářích pomocí značky @throws
► Nedělejte bloky try zbytečně velké,
kód uvnitř těchto bloků se neoptimalizuje
► Umíte-li výjimku v metodě ošetřit, udělejte to
► Detekuje-li se chyba v jedné metodě a má se ošetřit v jiné
(stejné či jiné instance), použijte výjimku.
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
31
Nejčastěji používané výjimky
1/2
► IllegalArgumentException
Byla zadána nepovolená hodnota parametru
● Např. chci nastavit zápornou velikost grafického tvaru
► IllegalStateException
V daném stavu objektu nelze metodu provést
● Např. otevřu soubor, přečtu pár vět, zavřu soubor a chci znovu přečíst větu
► NullPointerException
Byla vyvolána metoda instance, na níž ukazuje prázdný odkaz,
nebo byl předán nepovolený prázdný odkaz v parametru
► ArrayIndexOutOfBoundException
Byly zadány špatné meze pole, buď záporné nebo moc velké
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
32
Nejčastěji používané výjimky
2/2
► ConcurrentModificationException
V průběhu iterace byla změněna struktura kontejneru
● Např. byl do kontejneru přidán prvek
► NumberFormatException
Je požadován špatný převod řetězce na číslo či naopak
● Chci-li např. převést na číslo řetězec, který není číslem
● Častá chyba v metodách String.format či PrintStream.printf
► ClassCastException
Požadované přetypování není možné
► UnsupportedOperationException
Požadovaná operace není podporována
(např. chci přidat prvek do neměnného kontejneru)
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
33
Vaše jistota na trhu IT
Děkuji za pozornost
►Rudolf Pecinovský
http://vyuka.pecinovsky.cz/vse
mail: [email protected]
ICQ: 158 156 600
Slide 18
Vaše jistota na trhu IT
Výjimky
Rudolf Pecinovský
[email protected]
Vaše jistota na trhu IT
Obsah s odkazy
►Výjimky
►Výjimky kontrolované a nekontrolované
►Definice vlastních výjimek
Vaše jistota na trhu IT
Výjimky
►Výjimečné situace v programech
►Ošetření nestandardních situací v Javě
►Zpráva o výjimce
►Klíčová slova
►Činnost
►Vyvolání
Výjimečné situace v programech
► V každém programu je alespoň jedna chyba –
program na ni musí být připraven
► Starší programy
● Program vypsal chybové hlášení a ukončil činnost;
● V některých situacích (válcovací stolice, autopilot, …) nepřijatelné
● Funkce vrátí hodnotu signalizující chybu
● Programátor musí neustále testovat, co funkce vrací
● Knihovna měla pro tyto účely vyhrazenu speciální proměnnou,
do níž se v případě chyby zapsal její kód; nahlédnutím do proměnné
program zjistil kód poslední chyby
● Programátor musí neustále testovat, jaká je v proměnné hodnota
► Některé jazyky (Cobol, PL/1, …) proto přišly s koncepcí
ošetření nestandardních situací
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
4
Ošetření nestandardních situací v Javě
► Výjimečná událost =
problém, který brání dalšímu vykonávání části kódu
► Událost je výjimečná v tom, že na rozdíl od běžných problémů
nemá program k vyřešení situace dost informaci
► Program může při výskytu výjimečné události vyvolat výjimku
► Výjimka (exception)
objekt určený k přenosu informací o nastalém problému
z místa jeho vzniku do místa, kde bude problém řešen
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
5
Postup při vyvolání výjimky
1. Vytvoří se výjimka = objekt typu Throwable
(prakticky vždy instance některého z potomků)
2. Vytvořená výjimka se vyhodí =
přeruší se běh programu v místě, kde výjimka vznikla,
a začne se hledat místo, kde bude daná výjimka ošetřena
3. Ošetření výjimky (handler) by mělo uvést program do stavu,
v němž může jeho vykonávání pokračovat
► Výjimka „probublává“ programem z místa vyhození stále výše
a nenarazí-li cestou nikde na své ošetření,
zachytí ji virtuální stroj, který na standardní chybový výstup
vypíše zprávu o vzniku výjimky
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
6
Systémová zpráva o vzniku výjimky
Zpráva o vzniku výjimky spolu s názvem vlákna,
v němž k výjimce došlo (zde AWT-EventQueue-0)
Popis druhu výjimky (aritmetická výjimka dělení nulou)
Informace o místě, odkud byla volána metoda,
která vyvolala metodu, v níž došlo k vyhození výjimky
Informace o místě, odkud byla volána metoda,
v níž došlo k vyhození výjimky
Úplný název třídy včetně balíčku
Copyright © 2006, Rudolf Pecinovský
Název metody
VŠE – 05
Název souboru se
zdrojovým kódem
Číslo řádku zdrojáku,
kde došlo k výjimce
7
Klíčová slova související s výjimkami
► try (zkus)
Označuje blok kódu, v němž může dojít k výjimce
► throw (hoď)
Příkaz k vyhození výjimky;
musí být následován odkazem na existující instanci
► catch (chyť)
Blok ošetřující výjimku, která je zadána jako parametr
► finally (na konec)
Blok s povinnými závěrečnými akcemi nezávisejícími
na případném vzniku výjimky
► throws (hází)
Uvození seznamu výjimek vyhazovaných danou metodou
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
8
Vyvolání a ošetření výjimky v kódu
try {
//Kód, který může vyvolat výjimky
}
catch( Typ1 id1 ) {
//Ošetření výjimek typu Typ1
}
...
catch( TypN idN ) {
//ošetření výjimek typu TypN
}
finally {
//Kód, který se na závěr VŽDY provede
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
9
Náznak činnosti – řádný průběh
nedojde k vyvolání výjimky
= nedojde k chybě
try {
příkaz1();
příkaz2();
příkaz3();
}
catch ( xxxException e ) {
příkazProOšetřeníChyby();
}
Bloky catch
catch (…..
se přeskočí
finally {
ukončovacíPříkazy();
}
dalšíPříkaz();
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
12
Náznak činnosti – ošetřený výjimka
try {
příkaz1(); Při provádění metody příkaz2
dojde k ošetřené chybě
příkaz2();
příkaz3();
Byla vyhozena výjimka
tohoto typu nebo typu
}
některého z potomků
catch ( xxxException e ) {
příkazProOšetřeníChyby();
}
Ostatní bloky catch
catch (…..
se přeskočí
finally {
ukončovacíPříkazy();
}
dalšíPříkaz();
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
13
Náznak činnosti – neošetřená výjimka
Při provádění metody příkaz2
dojde k NEošetřené chybě
try {
příkaz1();
příkaz2();
příkaz3();
}
catch ( xxxException e ) {
příkazProOšetřeníChyby();
}
Ošetření nebylo nalezeno =>
catch (…..
provede se blok finally
a opouští se metoda
finally {
ukončovacíPříkazy();
}
dalšíPříkaz();
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
14
Vyvolání výjimky
public class Xyz implements Comparable
{
public bolean compareTo( Object o )
{
if( !(o instanceOf Xyz) )
throw new ClassCastException (
"\nPokus o porovnání s neporovnatelnou"
+ " instancí " + o );
//Zjištění, kdo je větší
return vysledek;
}
}
► Instanci nemusíme vytvářet až v příkazu throw,
můžeme ji vytvořit kdykoliv před tím a pak mu ji jen předat
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
15
Vaše jistota na trhu IT
Výjimky kontrolované a
nekontrolované
►Hierarchie výjimek
►Pořadí výjimek v blocích catch
►Metody generující výjimky
►Metody třídy Throwable
►Zřetězené výjimky
►Převod kontrolovaných na nekontrolované
Charakteristika
► Výjimky, které jsou potomky třídy RuntimeException
nebo Error označujeme jako nekontrolované (unchecked),
protože překladač nekontroluje, zda je na ně program připraven
► Ostatní výjimky označujeme jako kontrolované (checked),
protože překladač kontroluje dodržení pravidel:
● Každá metoda, která může vyhodit kontrolovanou výjimku,
se musí k této skutečnosti veřejně přihlásit
● Každé použití metody, která může vyhodit kontrolovanou výjimku,
musí být buď uzavřeno v bloku try…catch,
nebo se volající metoda musí přihlásit k tomu,
že může také vyhodit danou kontrolovanou výjimku
► Nekontrolované výjimky ohlašují chyby v programu,
kontrolované výjimky očekávatelné situace,
na jejichž výskyt má být program připraven
a měl by na ně umět reagovat
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
17
Hierarchie výjimek
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
18
Pořadí výjimek v blocích catch
► Třída NumberFormatException
je potomkem třídy RuntimeException
try {
Syntaktická chyba,
......
na druhý blok catch nikdy nedojde
}
catch (RuntimeException e) {
.........
}
Obrácené pořadí bloků catch
catch (NumberFormatException e){
vše vyřeší
........
try {
}
......
}
catch (NumberFormatException e) {
.........
}
catch (RuntimeException e){
........
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
19
Metody generující výjimky
► Java vyžaduje, aby programy, které používají metody
schopné vyvolat kontrolované výjimky,
byly o této schopnosti používaných metod informovány =>
pak vědí, které výjimku musí umět zachytit a ošetřit
► Všechny kontrolované výjimky, které může metoda vyhodit,
musí deklarovat v hlavičce za klíčovým slovem throws
► Deklarace vyhazování nekontrolovaných výjimek není povinná
public void metoda()
throws KontrolovanáVýjimka1,
KontrolovanáVýjimka2
{
// Tělo metody
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
20
Metody třídy Throwable
► String getMessage()
Vrátí zprávu popisující danou výjimku
► String toString()
Vrátí název třídy výjimky následovaný případnou zprávou
► void printStackTrace()
Vytiskne toString() následovaný sadou informací o volající
posloupnosti, která vedla k vzniku výjimky
► Throwable fillInStackTrace()
Připraví nové informace o volací posloupnosti
vedoucí k místu zavolání této metody
► StackTraceElement[] getStackTrace()
Vrátí uchované informace o volací posloupnosti dané výjimky
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
21
Zřetězené výjimky
► V některých situacích je vhodné v rámci ošetření výjimky vyvolat
jinou výjimku, a přitom umožnit zjistit,
která výjimka byla prvotním hybatelem celé akce
► Řada výjimek má mezi svými konstruktory i takové,
které akceptují jako poslední parametr
odkaz na výjimku, jež byla příčinou vyvolání dané výjimky
► Chce-li se program zeptat výjimky na výjimku, která ji způsobila,
použije metodu
public Throwable getCause()
► Ve zprávě o vyvolání výjimky jsou místa, kde byla jedna výjimka
nahrazena jinou, označována textem caused by:
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
22
Ukázka výpisu při zřetězení výjimek
HighLevelException: MidLevelException: LowLevelException
at Junk.a(Junk.java:13)
at Junk.main(Junk.java:4)
Caused by: MidLevelException: LowLevelException
at Junk.c(Junk.java:23)
at Junk.b(Junk.java:17)
at Junk.a(Junk.java:11)
... 1 more
Caused by: LowLevelException
at Junk.e(Junk.java:30)
at Junk.d(Junk.java:27)
at Junk.c(Junk.java:21)
... 3 more
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
23
Převod kontrolovaných na nekontrolované
► Ošetřování kontrolovaných výjimek obtěžuje
► Víme-li, že k dané výjimce nejspíš nedojde
a ošetřujeme-li ji pouze proto, že na tom překladač trvá,
můžeme pro případ, že by k výjimce přece jenom došlo
zaměnit kontrolovanou výjimku za nekontrolovanou
public void prevod( String s ) {
try {
prověř( s );
} catch( Exception ex ) {
throw new RuntimeException( " Neprověřeno! ", ex );
}
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
24
Vaše jistota na trhu IT
Definice vlastních výjimek
►Hierarchie výjimek
►Pořadí výjimek v blocích catch
►Metody generující výjimky
►Metody třídy Throwable
►Vlastní výjimky
►Zásady správného používání výjimek
Definice vlastních výjimek
► Výjimky jsou zcela běžné třídy;
považujeme-li to proto za vhodné, můžeme definovat i vlastní
► Před definicí nové výjimky bychom si měli ujasnit,
bude-li kontrolovaná či nekontrolovaná;
podle toho definujeme jejího předka
► Název výjimek končí dle konvencí slovem Exception
před nímž je naznačena podstata dané výjimky
● IllegalArgumetnException
● NoSuchMethodException
● BadStringOperationException
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
26
Příklad vlastní kontrolované výjimky
public class VelkýPrůšvihException
extends Exception
{
public VelkýPrůšvihException() {};
public VelkýPrůšvihException( String zpráva ) {
super( zpráva );
}
public VelkýPrůšvihException(String zpráva,
Throwable původce ) {
super( zpráva, původce );
}
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
27
Test správného vyhození výjimky
► Na vytvářených programech je třeba otestovat i to,
že v definovaných situacích vyhodí požadovanou výjimku
public void testVyhozeníVýjimky()
{
try {
metodaKteráMáVyhoditVýjimku();
} catch ( VelkýPrůšvihException vpe ) {
return;
}
fail( "Nebyla vyhozena výjimka VelkýPrůšvihException" );
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
28
Zásady správného používání výjimek
1/2
Neignorujte
výjimky
try {
//Nějaký kód
}
catch(Exception e){}
► Výjimky, o nichž víte, že nemohou nastat,
převeďte na nekontrolované pro případ,
že by v budoucích verzích programu nastat mohly
► Při ošetřování výjimek, které nastat mohou,
ale nemají vliv na chod programu,
vložte do těla ošetření alespoň vysvětlující komentář
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
29
Zásady správného používání výjimek
2/2
► Používejte výjimky pouze k ošetření výjimečných stavů
► Kontrolované výjimky používejte u stavů, z nichž se lze zotavit,
jinak použijte výjimky nekontrolované
► Vyhýbejte se zbytečnému používání kontrolovaných výjimek
● Programátory ošetřování kontrolovaných výjimek obtěžuje
a mají pak tendenci je ošetřovat prázdným blokem catch
► Dávejte přednost standardním výjimkám,
vyvolávejte výjimky odpovídající dané abstrakci
● Programátoři by měli z názvu výjimky poznat, co se stalo
● Standardní výjimky mají všeobecně známý význam
► Snažte se o atomičnost selhání; i po vyhození výjimky
by měl být objekt v dobře definovaném stavu
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
30
Zásady správného používání výjimek
3/2
► Doplňujte výjimky zprávami,
výjimka by sama měla poskytnout dostatek informací
a neměla by programátora nutit k podrobnější analýze programu
► Dokumentujte vyvolávané výjimky v dokumentačních
komentářích pomocí značky @throws
► Nedělejte bloky try zbytečně velké,
kód uvnitř těchto bloků se neoptimalizuje
► Umíte-li výjimku v metodě ošetřit, udělejte to
► Detekuje-li se chyba v jedné metodě a má se ošetřit v jiné
(stejné či jiné instance), použijte výjimku.
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
31
Nejčastěji používané výjimky
1/2
► IllegalArgumentException
Byla zadána nepovolená hodnota parametru
● Např. chci nastavit zápornou velikost grafického tvaru
► IllegalStateException
V daném stavu objektu nelze metodu provést
● Např. otevřu soubor, přečtu pár vět, zavřu soubor a chci znovu přečíst větu
► NullPointerException
Byla vyvolána metoda instance, na níž ukazuje prázdný odkaz,
nebo byl předán nepovolený prázdný odkaz v parametru
► ArrayIndexOutOfBoundException
Byly zadány špatné meze pole, buď záporné nebo moc velké
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
32
Nejčastěji používané výjimky
2/2
► ConcurrentModificationException
V průběhu iterace byla změněna struktura kontejneru
● Např. byl do kontejneru přidán prvek
► NumberFormatException
Je požadován špatný převod řetězce na číslo či naopak
● Chci-li např. převést na číslo řetězec, který není číslem
● Častá chyba v metodách String.format či PrintStream.printf
► ClassCastException
Požadované přetypování není možné
► UnsupportedOperationException
Požadovaná operace není podporována
(např. chci přidat prvek do neměnného kontejneru)
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
33
Vaše jistota na trhu IT
Děkuji za pozornost
►Rudolf Pecinovský
http://vyuka.pecinovsky.cz/vse
mail: [email protected]
ICQ: 158 156 600
Slide 19
Vaše jistota na trhu IT
Výjimky
Rudolf Pecinovský
[email protected]
Vaše jistota na trhu IT
Obsah s odkazy
►Výjimky
►Výjimky kontrolované a nekontrolované
►Definice vlastních výjimek
Vaše jistota na trhu IT
Výjimky
►Výjimečné situace v programech
►Ošetření nestandardních situací v Javě
►Zpráva o výjimce
►Klíčová slova
►Činnost
►Vyvolání
Výjimečné situace v programech
► V každém programu je alespoň jedna chyba –
program na ni musí být připraven
► Starší programy
● Program vypsal chybové hlášení a ukončil činnost;
● V některých situacích (válcovací stolice, autopilot, …) nepřijatelné
● Funkce vrátí hodnotu signalizující chybu
● Programátor musí neustále testovat, co funkce vrací
● Knihovna měla pro tyto účely vyhrazenu speciální proměnnou,
do níž se v případě chyby zapsal její kód; nahlédnutím do proměnné
program zjistil kód poslední chyby
● Programátor musí neustále testovat, jaká je v proměnné hodnota
► Některé jazyky (Cobol, PL/1, …) proto přišly s koncepcí
ošetření nestandardních situací
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
4
Ošetření nestandardních situací v Javě
► Výjimečná událost =
problém, který brání dalšímu vykonávání části kódu
► Událost je výjimečná v tom, že na rozdíl od běžných problémů
nemá program k vyřešení situace dost informaci
► Program může při výskytu výjimečné události vyvolat výjimku
► Výjimka (exception)
objekt určený k přenosu informací o nastalém problému
z místa jeho vzniku do místa, kde bude problém řešen
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
5
Postup při vyvolání výjimky
1. Vytvoří se výjimka = objekt typu Throwable
(prakticky vždy instance některého z potomků)
2. Vytvořená výjimka se vyhodí =
přeruší se běh programu v místě, kde výjimka vznikla,
a začne se hledat místo, kde bude daná výjimka ošetřena
3. Ošetření výjimky (handler) by mělo uvést program do stavu,
v němž může jeho vykonávání pokračovat
► Výjimka „probublává“ programem z místa vyhození stále výše
a nenarazí-li cestou nikde na své ošetření,
zachytí ji virtuální stroj, který na standardní chybový výstup
vypíše zprávu o vzniku výjimky
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
6
Systémová zpráva o vzniku výjimky
Zpráva o vzniku výjimky spolu s názvem vlákna,
v němž k výjimce došlo (zde AWT-EventQueue-0)
Popis druhu výjimky (aritmetická výjimka dělení nulou)
Informace o místě, odkud byla volána metoda,
která vyvolala metodu, v níž došlo k vyhození výjimky
Informace o místě, odkud byla volána metoda,
v níž došlo k vyhození výjimky
Úplný název třídy včetně balíčku
Copyright © 2006, Rudolf Pecinovský
Název metody
VŠE – 05
Název souboru se
zdrojovým kódem
Číslo řádku zdrojáku,
kde došlo k výjimce
7
Klíčová slova související s výjimkami
► try (zkus)
Označuje blok kódu, v němž může dojít k výjimce
► throw (hoď)
Příkaz k vyhození výjimky;
musí být následován odkazem na existující instanci
► catch (chyť)
Blok ošetřující výjimku, která je zadána jako parametr
► finally (na konec)
Blok s povinnými závěrečnými akcemi nezávisejícími
na případném vzniku výjimky
► throws (hází)
Uvození seznamu výjimek vyhazovaných danou metodou
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
8
Vyvolání a ošetření výjimky v kódu
try {
//Kód, který může vyvolat výjimky
}
catch( Typ1 id1 ) {
//Ošetření výjimek typu Typ1
}
...
catch( TypN idN ) {
//ošetření výjimek typu TypN
}
finally {
//Kód, který se na závěr VŽDY provede
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
9
Náznak činnosti – řádný průběh
nedojde k vyvolání výjimky
= nedojde k chybě
try {
příkaz1();
příkaz2();
příkaz3();
}
catch ( xxxException e ) {
příkazProOšetřeníChyby();
}
Bloky catch
catch (…..
se přeskočí
finally {
ukončovacíPříkazy();
}
dalšíPříkaz();
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
12
Náznak činnosti – ošetřený výjimka
try {
příkaz1(); Při provádění metody příkaz2
dojde k ošetřené chybě
příkaz2();
příkaz3();
Byla vyhozena výjimka
tohoto typu nebo typu
}
některého z potomků
catch ( xxxException e ) {
příkazProOšetřeníChyby();
}
Ostatní bloky catch
catch (…..
se přeskočí
finally {
ukončovacíPříkazy();
}
dalšíPříkaz();
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
13
Náznak činnosti – neošetřená výjimka
Při provádění metody příkaz2
dojde k NEošetřené chybě
try {
příkaz1();
příkaz2();
příkaz3();
}
catch ( xxxException e ) {
příkazProOšetřeníChyby();
}
Ošetření nebylo nalezeno =>
catch (…..
provede se blok finally
a opouští se metoda
finally {
ukončovacíPříkazy();
}
dalšíPříkaz();
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
14
Vyvolání výjimky
public class Xyz implements Comparable
{
public bolean compareTo( Object o )
{
if( !(o instanceOf Xyz) )
throw new ClassCastException (
"\nPokus o porovnání s neporovnatelnou"
+ " instancí " + o );
//Zjištění, kdo je větší
return vysledek;
}
}
► Instanci nemusíme vytvářet až v příkazu throw,
můžeme ji vytvořit kdykoliv před tím a pak mu ji jen předat
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
15
Vaše jistota na trhu IT
Výjimky kontrolované a
nekontrolované
►Hierarchie výjimek
►Pořadí výjimek v blocích catch
►Metody generující výjimky
►Metody třídy Throwable
►Zřetězené výjimky
►Převod kontrolovaných na nekontrolované
Charakteristika
► Výjimky, které jsou potomky třídy RuntimeException
nebo Error označujeme jako nekontrolované (unchecked),
protože překladač nekontroluje, zda je na ně program připraven
► Ostatní výjimky označujeme jako kontrolované (checked),
protože překladač kontroluje dodržení pravidel:
● Každá metoda, která může vyhodit kontrolovanou výjimku,
se musí k této skutečnosti veřejně přihlásit
● Každé použití metody, která může vyhodit kontrolovanou výjimku,
musí být buď uzavřeno v bloku try…catch,
nebo se volající metoda musí přihlásit k tomu,
že může také vyhodit danou kontrolovanou výjimku
► Nekontrolované výjimky ohlašují chyby v programu,
kontrolované výjimky očekávatelné situace,
na jejichž výskyt má být program připraven
a měl by na ně umět reagovat
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
17
Hierarchie výjimek
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
18
Pořadí výjimek v blocích catch
► Třída NumberFormatException
je potomkem třídy RuntimeException
try {
Syntaktická chyba,
......
na druhý blok catch nikdy nedojde
}
catch (RuntimeException e) {
.........
}
Obrácené pořadí bloků catch
catch (NumberFormatException e){
vše vyřeší
........
try {
}
......
}
catch (NumberFormatException e) {
.........
}
catch (RuntimeException e){
........
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
19
Metody generující výjimky
► Java vyžaduje, aby programy, které používají metody
schopné vyvolat kontrolované výjimky,
byly o této schopnosti používaných metod informovány =>
pak vědí, které výjimku musí umět zachytit a ošetřit
► Všechny kontrolované výjimky, které může metoda vyhodit,
musí deklarovat v hlavičce za klíčovým slovem throws
► Deklarace vyhazování nekontrolovaných výjimek není povinná
public void metoda()
throws KontrolovanáVýjimka1,
KontrolovanáVýjimka2
{
// Tělo metody
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
20
Metody třídy Throwable
► String getMessage()
Vrátí zprávu popisující danou výjimku
► String toString()
Vrátí název třídy výjimky následovaný případnou zprávou
► void printStackTrace()
Vytiskne toString() následovaný sadou informací o volající
posloupnosti, která vedla k vzniku výjimky
► Throwable fillInStackTrace()
Připraví nové informace o volací posloupnosti
vedoucí k místu zavolání této metody
► StackTraceElement[] getStackTrace()
Vrátí uchované informace o volací posloupnosti dané výjimky
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
21
Zřetězené výjimky
► V některých situacích je vhodné v rámci ošetření výjimky vyvolat
jinou výjimku, a přitom umožnit zjistit,
která výjimka byla prvotním hybatelem celé akce
► Řada výjimek má mezi svými konstruktory i takové,
které akceptují jako poslední parametr
odkaz na výjimku, jež byla příčinou vyvolání dané výjimky
► Chce-li se program zeptat výjimky na výjimku, která ji způsobila,
použije metodu
public Throwable getCause()
► Ve zprávě o vyvolání výjimky jsou místa, kde byla jedna výjimka
nahrazena jinou, označována textem caused by:
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
22
Ukázka výpisu při zřetězení výjimek
HighLevelException: MidLevelException: LowLevelException
at Junk.a(Junk.java:13)
at Junk.main(Junk.java:4)
Caused by: MidLevelException: LowLevelException
at Junk.c(Junk.java:23)
at Junk.b(Junk.java:17)
at Junk.a(Junk.java:11)
... 1 more
Caused by: LowLevelException
at Junk.e(Junk.java:30)
at Junk.d(Junk.java:27)
at Junk.c(Junk.java:21)
... 3 more
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
23
Převod kontrolovaných na nekontrolované
► Ošetřování kontrolovaných výjimek obtěžuje
► Víme-li, že k dané výjimce nejspíš nedojde
a ošetřujeme-li ji pouze proto, že na tom překladač trvá,
můžeme pro případ, že by k výjimce přece jenom došlo
zaměnit kontrolovanou výjimku za nekontrolovanou
public void prevod( String s ) {
try {
prověř( s );
} catch( Exception ex ) {
throw new RuntimeException( " Neprověřeno! ", ex );
}
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
24
Vaše jistota na trhu IT
Definice vlastních výjimek
►Hierarchie výjimek
►Pořadí výjimek v blocích catch
►Metody generující výjimky
►Metody třídy Throwable
►Vlastní výjimky
►Zásady správného používání výjimek
Definice vlastních výjimek
► Výjimky jsou zcela běžné třídy;
považujeme-li to proto za vhodné, můžeme definovat i vlastní
► Před definicí nové výjimky bychom si měli ujasnit,
bude-li kontrolovaná či nekontrolovaná;
podle toho definujeme jejího předka
► Název výjimek končí dle konvencí slovem Exception
před nímž je naznačena podstata dané výjimky
● IllegalArgumetnException
● NoSuchMethodException
● BadStringOperationException
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
26
Příklad vlastní kontrolované výjimky
public class VelkýPrůšvihException
extends Exception
{
public VelkýPrůšvihException() {};
public VelkýPrůšvihException( String zpráva ) {
super( zpráva );
}
public VelkýPrůšvihException(String zpráva,
Throwable původce ) {
super( zpráva, původce );
}
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
27
Test správného vyhození výjimky
► Na vytvářených programech je třeba otestovat i to,
že v definovaných situacích vyhodí požadovanou výjimku
public void testVyhozeníVýjimky()
{
try {
metodaKteráMáVyhoditVýjimku();
} catch ( VelkýPrůšvihException vpe ) {
return;
}
fail( "Nebyla vyhozena výjimka VelkýPrůšvihException" );
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
28
Zásady správného používání výjimek
1/2
Neignorujte
výjimky
try {
//Nějaký kód
}
catch(Exception e){}
► Výjimky, o nichž víte, že nemohou nastat,
převeďte na nekontrolované pro případ,
že by v budoucích verzích programu nastat mohly
► Při ošetřování výjimek, které nastat mohou,
ale nemají vliv na chod programu,
vložte do těla ošetření alespoň vysvětlující komentář
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
29
Zásady správného používání výjimek
2/2
► Používejte výjimky pouze k ošetření výjimečných stavů
► Kontrolované výjimky používejte u stavů, z nichž se lze zotavit,
jinak použijte výjimky nekontrolované
► Vyhýbejte se zbytečnému používání kontrolovaných výjimek
● Programátory ošetřování kontrolovaných výjimek obtěžuje
a mají pak tendenci je ošetřovat prázdným blokem catch
► Dávejte přednost standardním výjimkám,
vyvolávejte výjimky odpovídající dané abstrakci
● Programátoři by měli z názvu výjimky poznat, co se stalo
● Standardní výjimky mají všeobecně známý význam
► Snažte se o atomičnost selhání; i po vyhození výjimky
by měl být objekt v dobře definovaném stavu
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
30
Zásady správného používání výjimek
3/2
► Doplňujte výjimky zprávami,
výjimka by sama měla poskytnout dostatek informací
a neměla by programátora nutit k podrobnější analýze programu
► Dokumentujte vyvolávané výjimky v dokumentačních
komentářích pomocí značky @throws
► Nedělejte bloky try zbytečně velké,
kód uvnitř těchto bloků se neoptimalizuje
► Umíte-li výjimku v metodě ošetřit, udělejte to
► Detekuje-li se chyba v jedné metodě a má se ošetřit v jiné
(stejné či jiné instance), použijte výjimku.
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
31
Nejčastěji používané výjimky
1/2
► IllegalArgumentException
Byla zadána nepovolená hodnota parametru
● Např. chci nastavit zápornou velikost grafického tvaru
► IllegalStateException
V daném stavu objektu nelze metodu provést
● Např. otevřu soubor, přečtu pár vět, zavřu soubor a chci znovu přečíst větu
► NullPointerException
Byla vyvolána metoda instance, na níž ukazuje prázdný odkaz,
nebo byl předán nepovolený prázdný odkaz v parametru
► ArrayIndexOutOfBoundException
Byly zadány špatné meze pole, buď záporné nebo moc velké
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
32
Nejčastěji používané výjimky
2/2
► ConcurrentModificationException
V průběhu iterace byla změněna struktura kontejneru
● Např. byl do kontejneru přidán prvek
► NumberFormatException
Je požadován špatný převod řetězce na číslo či naopak
● Chci-li např. převést na číslo řetězec, který není číslem
● Častá chyba v metodách String.format či PrintStream.printf
► ClassCastException
Požadované přetypování není možné
► UnsupportedOperationException
Požadovaná operace není podporována
(např. chci přidat prvek do neměnného kontejneru)
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
33
Vaše jistota na trhu IT
Děkuji za pozornost
►Rudolf Pecinovský
http://vyuka.pecinovsky.cz/vse
mail: [email protected]
ICQ: 158 156 600
Slide 20
Vaše jistota na trhu IT
Výjimky
Rudolf Pecinovský
[email protected]
Vaše jistota na trhu IT
Obsah s odkazy
►Výjimky
►Výjimky kontrolované a nekontrolované
►Definice vlastních výjimek
Vaše jistota na trhu IT
Výjimky
►Výjimečné situace v programech
►Ošetření nestandardních situací v Javě
►Zpráva o výjimce
►Klíčová slova
►Činnost
►Vyvolání
Výjimečné situace v programech
► V každém programu je alespoň jedna chyba –
program na ni musí být připraven
► Starší programy
● Program vypsal chybové hlášení a ukončil činnost;
● V některých situacích (válcovací stolice, autopilot, …) nepřijatelné
● Funkce vrátí hodnotu signalizující chybu
● Programátor musí neustále testovat, co funkce vrací
● Knihovna měla pro tyto účely vyhrazenu speciální proměnnou,
do níž se v případě chyby zapsal její kód; nahlédnutím do proměnné
program zjistil kód poslední chyby
● Programátor musí neustále testovat, jaká je v proměnné hodnota
► Některé jazyky (Cobol, PL/1, …) proto přišly s koncepcí
ošetření nestandardních situací
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
4
Ošetření nestandardních situací v Javě
► Výjimečná událost =
problém, který brání dalšímu vykonávání části kódu
► Událost je výjimečná v tom, že na rozdíl od běžných problémů
nemá program k vyřešení situace dost informaci
► Program může při výskytu výjimečné události vyvolat výjimku
► Výjimka (exception)
objekt určený k přenosu informací o nastalém problému
z místa jeho vzniku do místa, kde bude problém řešen
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
5
Postup při vyvolání výjimky
1. Vytvoří se výjimka = objekt typu Throwable
(prakticky vždy instance některého z potomků)
2. Vytvořená výjimka se vyhodí =
přeruší se běh programu v místě, kde výjimka vznikla,
a začne se hledat místo, kde bude daná výjimka ošetřena
3. Ošetření výjimky (handler) by mělo uvést program do stavu,
v němž může jeho vykonávání pokračovat
► Výjimka „probublává“ programem z místa vyhození stále výše
a nenarazí-li cestou nikde na své ošetření,
zachytí ji virtuální stroj, který na standardní chybový výstup
vypíše zprávu o vzniku výjimky
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
6
Systémová zpráva o vzniku výjimky
Zpráva o vzniku výjimky spolu s názvem vlákna,
v němž k výjimce došlo (zde AWT-EventQueue-0)
Popis druhu výjimky (aritmetická výjimka dělení nulou)
Informace o místě, odkud byla volána metoda,
která vyvolala metodu, v níž došlo k vyhození výjimky
Informace o místě, odkud byla volána metoda,
v níž došlo k vyhození výjimky
Úplný název třídy včetně balíčku
Copyright © 2006, Rudolf Pecinovský
Název metody
VŠE – 05
Název souboru se
zdrojovým kódem
Číslo řádku zdrojáku,
kde došlo k výjimce
7
Klíčová slova související s výjimkami
► try (zkus)
Označuje blok kódu, v němž může dojít k výjimce
► throw (hoď)
Příkaz k vyhození výjimky;
musí být následován odkazem na existující instanci
► catch (chyť)
Blok ošetřující výjimku, která je zadána jako parametr
► finally (na konec)
Blok s povinnými závěrečnými akcemi nezávisejícími
na případném vzniku výjimky
► throws (hází)
Uvození seznamu výjimek vyhazovaných danou metodou
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
8
Vyvolání a ošetření výjimky v kódu
try {
//Kód, který může vyvolat výjimky
}
catch( Typ1 id1 ) {
//Ošetření výjimek typu Typ1
}
...
catch( TypN idN ) {
//ošetření výjimek typu TypN
}
finally {
//Kód, který se na závěr VŽDY provede
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
9
Náznak činnosti – řádný průběh
nedojde k vyvolání výjimky
= nedojde k chybě
try {
příkaz1();
příkaz2();
příkaz3();
}
catch ( xxxException e ) {
příkazProOšetřeníChyby();
}
Bloky catch
catch (…..
se přeskočí
finally {
ukončovacíPříkazy();
}
dalšíPříkaz();
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
12
Náznak činnosti – ošetřený výjimka
try {
příkaz1(); Při provádění metody příkaz2
dojde k ošetřené chybě
příkaz2();
příkaz3();
Byla vyhozena výjimka
tohoto typu nebo typu
}
některého z potomků
catch ( xxxException e ) {
příkazProOšetřeníChyby();
}
Ostatní bloky catch
catch (…..
se přeskočí
finally {
ukončovacíPříkazy();
}
dalšíPříkaz();
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
13
Náznak činnosti – neošetřená výjimka
Při provádění metody příkaz2
dojde k NEošetřené chybě
try {
příkaz1();
příkaz2();
příkaz3();
}
catch ( xxxException e ) {
příkazProOšetřeníChyby();
}
Ošetření nebylo nalezeno =>
catch (…..
provede se blok finally
a opouští se metoda
finally {
ukončovacíPříkazy();
}
dalšíPříkaz();
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
14
Vyvolání výjimky
public class Xyz implements Comparable
{
public bolean compareTo( Object o )
{
if( !(o instanceOf Xyz) )
throw new ClassCastException (
"\nPokus o porovnání s neporovnatelnou"
+ " instancí " + o );
//Zjištění, kdo je větší
return vysledek;
}
}
► Instanci nemusíme vytvářet až v příkazu throw,
můžeme ji vytvořit kdykoliv před tím a pak mu ji jen předat
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
15
Vaše jistota na trhu IT
Výjimky kontrolované a
nekontrolované
►Hierarchie výjimek
►Pořadí výjimek v blocích catch
►Metody generující výjimky
►Metody třídy Throwable
►Zřetězené výjimky
►Převod kontrolovaných na nekontrolované
Charakteristika
► Výjimky, které jsou potomky třídy RuntimeException
nebo Error označujeme jako nekontrolované (unchecked),
protože překladač nekontroluje, zda je na ně program připraven
► Ostatní výjimky označujeme jako kontrolované (checked),
protože překladač kontroluje dodržení pravidel:
● Každá metoda, která může vyhodit kontrolovanou výjimku,
se musí k této skutečnosti veřejně přihlásit
● Každé použití metody, která může vyhodit kontrolovanou výjimku,
musí být buď uzavřeno v bloku try…catch,
nebo se volající metoda musí přihlásit k tomu,
že může také vyhodit danou kontrolovanou výjimku
► Nekontrolované výjimky ohlašují chyby v programu,
kontrolované výjimky očekávatelné situace,
na jejichž výskyt má být program připraven
a měl by na ně umět reagovat
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
17
Hierarchie výjimek
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
18
Pořadí výjimek v blocích catch
► Třída NumberFormatException
je potomkem třídy RuntimeException
try {
Syntaktická chyba,
......
na druhý blok catch nikdy nedojde
}
catch (RuntimeException e) {
.........
}
Obrácené pořadí bloků catch
catch (NumberFormatException e){
vše vyřeší
........
try {
}
......
}
catch (NumberFormatException e) {
.........
}
catch (RuntimeException e){
........
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
19
Metody generující výjimky
► Java vyžaduje, aby programy, které používají metody
schopné vyvolat kontrolované výjimky,
byly o této schopnosti používaných metod informovány =>
pak vědí, které výjimku musí umět zachytit a ošetřit
► Všechny kontrolované výjimky, které může metoda vyhodit,
musí deklarovat v hlavičce za klíčovým slovem throws
► Deklarace vyhazování nekontrolovaných výjimek není povinná
public void metoda()
throws KontrolovanáVýjimka1,
KontrolovanáVýjimka2
{
// Tělo metody
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
20
Metody třídy Throwable
► String getMessage()
Vrátí zprávu popisující danou výjimku
► String toString()
Vrátí název třídy výjimky následovaný případnou zprávou
► void printStackTrace()
Vytiskne toString() následovaný sadou informací o volající
posloupnosti, která vedla k vzniku výjimky
► Throwable fillInStackTrace()
Připraví nové informace o volací posloupnosti
vedoucí k místu zavolání této metody
► StackTraceElement[] getStackTrace()
Vrátí uchované informace o volací posloupnosti dané výjimky
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
21
Zřetězené výjimky
► V některých situacích je vhodné v rámci ošetření výjimky vyvolat
jinou výjimku, a přitom umožnit zjistit,
která výjimka byla prvotním hybatelem celé akce
► Řada výjimek má mezi svými konstruktory i takové,
které akceptují jako poslední parametr
odkaz na výjimku, jež byla příčinou vyvolání dané výjimky
► Chce-li se program zeptat výjimky na výjimku, která ji způsobila,
použije metodu
public Throwable getCause()
► Ve zprávě o vyvolání výjimky jsou místa, kde byla jedna výjimka
nahrazena jinou, označována textem caused by:
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
22
Ukázka výpisu při zřetězení výjimek
HighLevelException: MidLevelException: LowLevelException
at Junk.a(Junk.java:13)
at Junk.main(Junk.java:4)
Caused by: MidLevelException: LowLevelException
at Junk.c(Junk.java:23)
at Junk.b(Junk.java:17)
at Junk.a(Junk.java:11)
... 1 more
Caused by: LowLevelException
at Junk.e(Junk.java:30)
at Junk.d(Junk.java:27)
at Junk.c(Junk.java:21)
... 3 more
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
23
Převod kontrolovaných na nekontrolované
► Ošetřování kontrolovaných výjimek obtěžuje
► Víme-li, že k dané výjimce nejspíš nedojde
a ošetřujeme-li ji pouze proto, že na tom překladač trvá,
můžeme pro případ, že by k výjimce přece jenom došlo
zaměnit kontrolovanou výjimku za nekontrolovanou
public void prevod( String s ) {
try {
prověř( s );
} catch( Exception ex ) {
throw new RuntimeException( " Neprověřeno! ", ex );
}
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
24
Vaše jistota na trhu IT
Definice vlastních výjimek
►Hierarchie výjimek
►Pořadí výjimek v blocích catch
►Metody generující výjimky
►Metody třídy Throwable
►Vlastní výjimky
►Zásady správného používání výjimek
Definice vlastních výjimek
► Výjimky jsou zcela běžné třídy;
považujeme-li to proto za vhodné, můžeme definovat i vlastní
► Před definicí nové výjimky bychom si měli ujasnit,
bude-li kontrolovaná či nekontrolovaná;
podle toho definujeme jejího předka
► Název výjimek končí dle konvencí slovem Exception
před nímž je naznačena podstata dané výjimky
● IllegalArgumetnException
● NoSuchMethodException
● BadStringOperationException
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
26
Příklad vlastní kontrolované výjimky
public class VelkýPrůšvihException
extends Exception
{
public VelkýPrůšvihException() {};
public VelkýPrůšvihException( String zpráva ) {
super( zpráva );
}
public VelkýPrůšvihException(String zpráva,
Throwable původce ) {
super( zpráva, původce );
}
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
27
Test správného vyhození výjimky
► Na vytvářených programech je třeba otestovat i to,
že v definovaných situacích vyhodí požadovanou výjimku
public void testVyhozeníVýjimky()
{
try {
metodaKteráMáVyhoditVýjimku();
} catch ( VelkýPrůšvihException vpe ) {
return;
}
fail( "Nebyla vyhozena výjimka VelkýPrůšvihException" );
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
28
Zásady správného používání výjimek
1/2
Neignorujte
výjimky
try {
//Nějaký kód
}
catch(Exception e){}
► Výjimky, o nichž víte, že nemohou nastat,
převeďte na nekontrolované pro případ,
že by v budoucích verzích programu nastat mohly
► Při ošetřování výjimek, které nastat mohou,
ale nemají vliv na chod programu,
vložte do těla ošetření alespoň vysvětlující komentář
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
29
Zásady správného používání výjimek
2/2
► Používejte výjimky pouze k ošetření výjimečných stavů
► Kontrolované výjimky používejte u stavů, z nichž se lze zotavit,
jinak použijte výjimky nekontrolované
► Vyhýbejte se zbytečnému používání kontrolovaných výjimek
● Programátory ošetřování kontrolovaných výjimek obtěžuje
a mají pak tendenci je ošetřovat prázdným blokem catch
► Dávejte přednost standardním výjimkám,
vyvolávejte výjimky odpovídající dané abstrakci
● Programátoři by měli z názvu výjimky poznat, co se stalo
● Standardní výjimky mají všeobecně známý význam
► Snažte se o atomičnost selhání; i po vyhození výjimky
by měl být objekt v dobře definovaném stavu
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
30
Zásady správného používání výjimek
3/2
► Doplňujte výjimky zprávami,
výjimka by sama měla poskytnout dostatek informací
a neměla by programátora nutit k podrobnější analýze programu
► Dokumentujte vyvolávané výjimky v dokumentačních
komentářích pomocí značky @throws
► Nedělejte bloky try zbytečně velké,
kód uvnitř těchto bloků se neoptimalizuje
► Umíte-li výjimku v metodě ošetřit, udělejte to
► Detekuje-li se chyba v jedné metodě a má se ošetřit v jiné
(stejné či jiné instance), použijte výjimku.
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
31
Nejčastěji používané výjimky
1/2
► IllegalArgumentException
Byla zadána nepovolená hodnota parametru
● Např. chci nastavit zápornou velikost grafického tvaru
► IllegalStateException
V daném stavu objektu nelze metodu provést
● Např. otevřu soubor, přečtu pár vět, zavřu soubor a chci znovu přečíst větu
► NullPointerException
Byla vyvolána metoda instance, na níž ukazuje prázdný odkaz,
nebo byl předán nepovolený prázdný odkaz v parametru
► ArrayIndexOutOfBoundException
Byly zadány špatné meze pole, buď záporné nebo moc velké
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
32
Nejčastěji používané výjimky
2/2
► ConcurrentModificationException
V průběhu iterace byla změněna struktura kontejneru
● Např. byl do kontejneru přidán prvek
► NumberFormatException
Je požadován špatný převod řetězce na číslo či naopak
● Chci-li např. převést na číslo řetězec, který není číslem
● Častá chyba v metodách String.format či PrintStream.printf
► ClassCastException
Požadované přetypování není možné
► UnsupportedOperationException
Požadovaná operace není podporována
(např. chci přidat prvek do neměnného kontejneru)
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
33
Vaše jistota na trhu IT
Děkuji za pozornost
►Rudolf Pecinovský
http://vyuka.pecinovsky.cz/vse
mail: [email protected]
ICQ: 158 156 600
Slide 21
Vaše jistota na trhu IT
Výjimky
Rudolf Pecinovský
[email protected]
Vaše jistota na trhu IT
Obsah s odkazy
►Výjimky
►Výjimky kontrolované a nekontrolované
►Definice vlastních výjimek
Vaše jistota na trhu IT
Výjimky
►Výjimečné situace v programech
►Ošetření nestandardních situací v Javě
►Zpráva o výjimce
►Klíčová slova
►Činnost
►Vyvolání
Výjimečné situace v programech
► V každém programu je alespoň jedna chyba –
program na ni musí být připraven
► Starší programy
● Program vypsal chybové hlášení a ukončil činnost;
● V některých situacích (válcovací stolice, autopilot, …) nepřijatelné
● Funkce vrátí hodnotu signalizující chybu
● Programátor musí neustále testovat, co funkce vrací
● Knihovna měla pro tyto účely vyhrazenu speciální proměnnou,
do níž se v případě chyby zapsal její kód; nahlédnutím do proměnné
program zjistil kód poslední chyby
● Programátor musí neustále testovat, jaká je v proměnné hodnota
► Některé jazyky (Cobol, PL/1, …) proto přišly s koncepcí
ošetření nestandardních situací
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
4
Ošetření nestandardních situací v Javě
► Výjimečná událost =
problém, který brání dalšímu vykonávání části kódu
► Událost je výjimečná v tom, že na rozdíl od běžných problémů
nemá program k vyřešení situace dost informaci
► Program může při výskytu výjimečné události vyvolat výjimku
► Výjimka (exception)
objekt určený k přenosu informací o nastalém problému
z místa jeho vzniku do místa, kde bude problém řešen
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
5
Postup při vyvolání výjimky
1. Vytvoří se výjimka = objekt typu Throwable
(prakticky vždy instance některého z potomků)
2. Vytvořená výjimka se vyhodí =
přeruší se běh programu v místě, kde výjimka vznikla,
a začne se hledat místo, kde bude daná výjimka ošetřena
3. Ošetření výjimky (handler) by mělo uvést program do stavu,
v němž může jeho vykonávání pokračovat
► Výjimka „probublává“ programem z místa vyhození stále výše
a nenarazí-li cestou nikde na své ošetření,
zachytí ji virtuální stroj, který na standardní chybový výstup
vypíše zprávu o vzniku výjimky
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
6
Systémová zpráva o vzniku výjimky
Zpráva o vzniku výjimky spolu s názvem vlákna,
v němž k výjimce došlo (zde AWT-EventQueue-0)
Popis druhu výjimky (aritmetická výjimka dělení nulou)
Informace o místě, odkud byla volána metoda,
která vyvolala metodu, v níž došlo k vyhození výjimky
Informace o místě, odkud byla volána metoda,
v níž došlo k vyhození výjimky
Úplný název třídy včetně balíčku
Copyright © 2006, Rudolf Pecinovský
Název metody
VŠE – 05
Název souboru se
zdrojovým kódem
Číslo řádku zdrojáku,
kde došlo k výjimce
7
Klíčová slova související s výjimkami
► try (zkus)
Označuje blok kódu, v němž může dojít k výjimce
► throw (hoď)
Příkaz k vyhození výjimky;
musí být následován odkazem na existující instanci
► catch (chyť)
Blok ošetřující výjimku, která je zadána jako parametr
► finally (na konec)
Blok s povinnými závěrečnými akcemi nezávisejícími
na případném vzniku výjimky
► throws (hází)
Uvození seznamu výjimek vyhazovaných danou metodou
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
8
Vyvolání a ošetření výjimky v kódu
try {
//Kód, který může vyvolat výjimky
}
catch( Typ1 id1 ) {
//Ošetření výjimek typu Typ1
}
...
catch( TypN idN ) {
//ošetření výjimek typu TypN
}
finally {
//Kód, který se na závěr VŽDY provede
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
9
Náznak činnosti – řádný průběh
nedojde k vyvolání výjimky
= nedojde k chybě
try {
příkaz1();
příkaz2();
příkaz3();
}
catch ( xxxException e ) {
příkazProOšetřeníChyby();
}
Bloky catch
catch (…..
se přeskočí
finally {
ukončovacíPříkazy();
}
dalšíPříkaz();
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
12
Náznak činnosti – ošetřený výjimka
try {
příkaz1(); Při provádění metody příkaz2
dojde k ošetřené chybě
příkaz2();
příkaz3();
Byla vyhozena výjimka
tohoto typu nebo typu
}
některého z potomků
catch ( xxxException e ) {
příkazProOšetřeníChyby();
}
Ostatní bloky catch
catch (…..
se přeskočí
finally {
ukončovacíPříkazy();
}
dalšíPříkaz();
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
13
Náznak činnosti – neošetřená výjimka
Při provádění metody příkaz2
dojde k NEošetřené chybě
try {
příkaz1();
příkaz2();
příkaz3();
}
catch ( xxxException e ) {
příkazProOšetřeníChyby();
}
Ošetření nebylo nalezeno =>
catch (…..
provede se blok finally
a opouští se metoda
finally {
ukončovacíPříkazy();
}
dalšíPříkaz();
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
14
Vyvolání výjimky
public class Xyz implements Comparable
{
public bolean compareTo( Object o )
{
if( !(o instanceOf Xyz) )
throw new ClassCastException (
"\nPokus o porovnání s neporovnatelnou"
+ " instancí " + o );
//Zjištění, kdo je větší
return vysledek;
}
}
► Instanci nemusíme vytvářet až v příkazu throw,
můžeme ji vytvořit kdykoliv před tím a pak mu ji jen předat
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
15
Vaše jistota na trhu IT
Výjimky kontrolované a
nekontrolované
►Hierarchie výjimek
►Pořadí výjimek v blocích catch
►Metody generující výjimky
►Metody třídy Throwable
►Zřetězené výjimky
►Převod kontrolovaných na nekontrolované
Charakteristika
► Výjimky, které jsou potomky třídy RuntimeException
nebo Error označujeme jako nekontrolované (unchecked),
protože překladač nekontroluje, zda je na ně program připraven
► Ostatní výjimky označujeme jako kontrolované (checked),
protože překladač kontroluje dodržení pravidel:
● Každá metoda, která může vyhodit kontrolovanou výjimku,
se musí k této skutečnosti veřejně přihlásit
● Každé použití metody, která může vyhodit kontrolovanou výjimku,
musí být buď uzavřeno v bloku try…catch,
nebo se volající metoda musí přihlásit k tomu,
že může také vyhodit danou kontrolovanou výjimku
► Nekontrolované výjimky ohlašují chyby v programu,
kontrolované výjimky očekávatelné situace,
na jejichž výskyt má být program připraven
a měl by na ně umět reagovat
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
17
Hierarchie výjimek
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
18
Pořadí výjimek v blocích catch
► Třída NumberFormatException
je potomkem třídy RuntimeException
try {
Syntaktická chyba,
......
na druhý blok catch nikdy nedojde
}
catch (RuntimeException e) {
.........
}
Obrácené pořadí bloků catch
catch (NumberFormatException e){
vše vyřeší
........
try {
}
......
}
catch (NumberFormatException e) {
.........
}
catch (RuntimeException e){
........
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
19
Metody generující výjimky
► Java vyžaduje, aby programy, které používají metody
schopné vyvolat kontrolované výjimky,
byly o této schopnosti používaných metod informovány =>
pak vědí, které výjimku musí umět zachytit a ošetřit
► Všechny kontrolované výjimky, které může metoda vyhodit,
musí deklarovat v hlavičce za klíčovým slovem throws
► Deklarace vyhazování nekontrolovaných výjimek není povinná
public void metoda()
throws KontrolovanáVýjimka1,
KontrolovanáVýjimka2
{
// Tělo metody
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
20
Metody třídy Throwable
► String getMessage()
Vrátí zprávu popisující danou výjimku
► String toString()
Vrátí název třídy výjimky následovaný případnou zprávou
► void printStackTrace()
Vytiskne toString() následovaný sadou informací o volající
posloupnosti, která vedla k vzniku výjimky
► Throwable fillInStackTrace()
Připraví nové informace o volací posloupnosti
vedoucí k místu zavolání této metody
► StackTraceElement[] getStackTrace()
Vrátí uchované informace o volací posloupnosti dané výjimky
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
21
Zřetězené výjimky
► V některých situacích je vhodné v rámci ošetření výjimky vyvolat
jinou výjimku, a přitom umožnit zjistit,
která výjimka byla prvotním hybatelem celé akce
► Řada výjimek má mezi svými konstruktory i takové,
které akceptují jako poslední parametr
odkaz na výjimku, jež byla příčinou vyvolání dané výjimky
► Chce-li se program zeptat výjimky na výjimku, která ji způsobila,
použije metodu
public Throwable getCause()
► Ve zprávě o vyvolání výjimky jsou místa, kde byla jedna výjimka
nahrazena jinou, označována textem caused by:
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
22
Ukázka výpisu při zřetězení výjimek
HighLevelException: MidLevelException: LowLevelException
at Junk.a(Junk.java:13)
at Junk.main(Junk.java:4)
Caused by: MidLevelException: LowLevelException
at Junk.c(Junk.java:23)
at Junk.b(Junk.java:17)
at Junk.a(Junk.java:11)
... 1 more
Caused by: LowLevelException
at Junk.e(Junk.java:30)
at Junk.d(Junk.java:27)
at Junk.c(Junk.java:21)
... 3 more
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
23
Převod kontrolovaných na nekontrolované
► Ošetřování kontrolovaných výjimek obtěžuje
► Víme-li, že k dané výjimce nejspíš nedojde
a ošetřujeme-li ji pouze proto, že na tom překladač trvá,
můžeme pro případ, že by k výjimce přece jenom došlo
zaměnit kontrolovanou výjimku za nekontrolovanou
public void prevod( String s ) {
try {
prověř( s );
} catch( Exception ex ) {
throw new RuntimeException( " Neprověřeno! ", ex );
}
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
24
Vaše jistota na trhu IT
Definice vlastních výjimek
►Hierarchie výjimek
►Pořadí výjimek v blocích catch
►Metody generující výjimky
►Metody třídy Throwable
►Vlastní výjimky
►Zásady správného používání výjimek
Definice vlastních výjimek
► Výjimky jsou zcela běžné třídy;
považujeme-li to proto za vhodné, můžeme definovat i vlastní
► Před definicí nové výjimky bychom si měli ujasnit,
bude-li kontrolovaná či nekontrolovaná;
podle toho definujeme jejího předka
► Název výjimek končí dle konvencí slovem Exception
před nímž je naznačena podstata dané výjimky
● IllegalArgumetnException
● NoSuchMethodException
● BadStringOperationException
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
26
Příklad vlastní kontrolované výjimky
public class VelkýPrůšvihException
extends Exception
{
public VelkýPrůšvihException() {};
public VelkýPrůšvihException( String zpráva ) {
super( zpráva );
}
public VelkýPrůšvihException(String zpráva,
Throwable původce ) {
super( zpráva, původce );
}
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
27
Test správného vyhození výjimky
► Na vytvářených programech je třeba otestovat i to,
že v definovaných situacích vyhodí požadovanou výjimku
public void testVyhozeníVýjimky()
{
try {
metodaKteráMáVyhoditVýjimku();
} catch ( VelkýPrůšvihException vpe ) {
return;
}
fail( "Nebyla vyhozena výjimka VelkýPrůšvihException" );
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
28
Zásady správného používání výjimek
1/2
Neignorujte
výjimky
try {
//Nějaký kód
}
catch(Exception e){}
► Výjimky, o nichž víte, že nemohou nastat,
převeďte na nekontrolované pro případ,
že by v budoucích verzích programu nastat mohly
► Při ošetřování výjimek, které nastat mohou,
ale nemají vliv na chod programu,
vložte do těla ošetření alespoň vysvětlující komentář
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
29
Zásady správného používání výjimek
2/2
► Používejte výjimky pouze k ošetření výjimečných stavů
► Kontrolované výjimky používejte u stavů, z nichž se lze zotavit,
jinak použijte výjimky nekontrolované
► Vyhýbejte se zbytečnému používání kontrolovaných výjimek
● Programátory ošetřování kontrolovaných výjimek obtěžuje
a mají pak tendenci je ošetřovat prázdným blokem catch
► Dávejte přednost standardním výjimkám,
vyvolávejte výjimky odpovídající dané abstrakci
● Programátoři by měli z názvu výjimky poznat, co se stalo
● Standardní výjimky mají všeobecně známý význam
► Snažte se o atomičnost selhání; i po vyhození výjimky
by měl být objekt v dobře definovaném stavu
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
30
Zásady správného používání výjimek
3/2
► Doplňujte výjimky zprávami,
výjimka by sama měla poskytnout dostatek informací
a neměla by programátora nutit k podrobnější analýze programu
► Dokumentujte vyvolávané výjimky v dokumentačních
komentářích pomocí značky @throws
► Nedělejte bloky try zbytečně velké,
kód uvnitř těchto bloků se neoptimalizuje
► Umíte-li výjimku v metodě ošetřit, udělejte to
► Detekuje-li se chyba v jedné metodě a má se ošetřit v jiné
(stejné či jiné instance), použijte výjimku.
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
31
Nejčastěji používané výjimky
1/2
► IllegalArgumentException
Byla zadána nepovolená hodnota parametru
● Např. chci nastavit zápornou velikost grafického tvaru
► IllegalStateException
V daném stavu objektu nelze metodu provést
● Např. otevřu soubor, přečtu pár vět, zavřu soubor a chci znovu přečíst větu
► NullPointerException
Byla vyvolána metoda instance, na níž ukazuje prázdný odkaz,
nebo byl předán nepovolený prázdný odkaz v parametru
► ArrayIndexOutOfBoundException
Byly zadány špatné meze pole, buď záporné nebo moc velké
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
32
Nejčastěji používané výjimky
2/2
► ConcurrentModificationException
V průběhu iterace byla změněna struktura kontejneru
● Např. byl do kontejneru přidán prvek
► NumberFormatException
Je požadován špatný převod řetězce na číslo či naopak
● Chci-li např. převést na číslo řetězec, který není číslem
● Častá chyba v metodách String.format či PrintStream.printf
► ClassCastException
Požadované přetypování není možné
► UnsupportedOperationException
Požadovaná operace není podporována
(např. chci přidat prvek do neměnného kontejneru)
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
33
Vaše jistota na trhu IT
Děkuji za pozornost
►Rudolf Pecinovský
http://vyuka.pecinovsky.cz/vse
mail: [email protected]
ICQ: 158 156 600
Slide 22
Vaše jistota na trhu IT
Výjimky
Rudolf Pecinovský
[email protected]
Vaše jistota na trhu IT
Obsah s odkazy
►Výjimky
►Výjimky kontrolované a nekontrolované
►Definice vlastních výjimek
Vaše jistota na trhu IT
Výjimky
►Výjimečné situace v programech
►Ošetření nestandardních situací v Javě
►Zpráva o výjimce
►Klíčová slova
►Činnost
►Vyvolání
Výjimečné situace v programech
► V každém programu je alespoň jedna chyba –
program na ni musí být připraven
► Starší programy
● Program vypsal chybové hlášení a ukončil činnost;
● V některých situacích (válcovací stolice, autopilot, …) nepřijatelné
● Funkce vrátí hodnotu signalizující chybu
● Programátor musí neustále testovat, co funkce vrací
● Knihovna měla pro tyto účely vyhrazenu speciální proměnnou,
do níž se v případě chyby zapsal její kód; nahlédnutím do proměnné
program zjistil kód poslední chyby
● Programátor musí neustále testovat, jaká je v proměnné hodnota
► Některé jazyky (Cobol, PL/1, …) proto přišly s koncepcí
ošetření nestandardních situací
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
4
Ošetření nestandardních situací v Javě
► Výjimečná událost =
problém, který brání dalšímu vykonávání části kódu
► Událost je výjimečná v tom, že na rozdíl od běžných problémů
nemá program k vyřešení situace dost informaci
► Program může při výskytu výjimečné události vyvolat výjimku
► Výjimka (exception)
objekt určený k přenosu informací o nastalém problému
z místa jeho vzniku do místa, kde bude problém řešen
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
5
Postup při vyvolání výjimky
1. Vytvoří se výjimka = objekt typu Throwable
(prakticky vždy instance některého z potomků)
2. Vytvořená výjimka se vyhodí =
přeruší se běh programu v místě, kde výjimka vznikla,
a začne se hledat místo, kde bude daná výjimka ošetřena
3. Ošetření výjimky (handler) by mělo uvést program do stavu,
v němž může jeho vykonávání pokračovat
► Výjimka „probublává“ programem z místa vyhození stále výše
a nenarazí-li cestou nikde na své ošetření,
zachytí ji virtuální stroj, který na standardní chybový výstup
vypíše zprávu o vzniku výjimky
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
6
Systémová zpráva o vzniku výjimky
Zpráva o vzniku výjimky spolu s názvem vlákna,
v němž k výjimce došlo (zde AWT-EventQueue-0)
Popis druhu výjimky (aritmetická výjimka dělení nulou)
Informace o místě, odkud byla volána metoda,
která vyvolala metodu, v níž došlo k vyhození výjimky
Informace o místě, odkud byla volána metoda,
v níž došlo k vyhození výjimky
Úplný název třídy včetně balíčku
Copyright © 2006, Rudolf Pecinovský
Název metody
VŠE – 05
Název souboru se
zdrojovým kódem
Číslo řádku zdrojáku,
kde došlo k výjimce
7
Klíčová slova související s výjimkami
► try (zkus)
Označuje blok kódu, v němž může dojít k výjimce
► throw (hoď)
Příkaz k vyhození výjimky;
musí být následován odkazem na existující instanci
► catch (chyť)
Blok ošetřující výjimku, která je zadána jako parametr
► finally (na konec)
Blok s povinnými závěrečnými akcemi nezávisejícími
na případném vzniku výjimky
► throws (hází)
Uvození seznamu výjimek vyhazovaných danou metodou
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
8
Vyvolání a ošetření výjimky v kódu
try {
//Kód, který může vyvolat výjimky
}
catch( Typ1 id1 ) {
//Ošetření výjimek typu Typ1
}
...
catch( TypN idN ) {
//ošetření výjimek typu TypN
}
finally {
//Kód, který se na závěr VŽDY provede
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
9
Náznak činnosti – řádný průběh
nedojde k vyvolání výjimky
= nedojde k chybě
try {
příkaz1();
příkaz2();
příkaz3();
}
catch ( xxxException e ) {
příkazProOšetřeníChyby();
}
Bloky catch
catch (…..
se přeskočí
finally {
ukončovacíPříkazy();
}
dalšíPříkaz();
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
12
Náznak činnosti – ošetřený výjimka
try {
příkaz1(); Při provádění metody příkaz2
dojde k ošetřené chybě
příkaz2();
příkaz3();
Byla vyhozena výjimka
tohoto typu nebo typu
}
některého z potomků
catch ( xxxException e ) {
příkazProOšetřeníChyby();
}
Ostatní bloky catch
catch (…..
se přeskočí
finally {
ukončovacíPříkazy();
}
dalšíPříkaz();
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
13
Náznak činnosti – neošetřená výjimka
Při provádění metody příkaz2
dojde k NEošetřené chybě
try {
příkaz1();
příkaz2();
příkaz3();
}
catch ( xxxException e ) {
příkazProOšetřeníChyby();
}
Ošetření nebylo nalezeno =>
catch (…..
provede se blok finally
a opouští se metoda
finally {
ukončovacíPříkazy();
}
dalšíPříkaz();
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
14
Vyvolání výjimky
public class Xyz implements Comparable
{
public bolean compareTo( Object o )
{
if( !(o instanceOf Xyz) )
throw new ClassCastException (
"\nPokus o porovnání s neporovnatelnou"
+ " instancí " + o );
//Zjištění, kdo je větší
return vysledek;
}
}
► Instanci nemusíme vytvářet až v příkazu throw,
můžeme ji vytvořit kdykoliv před tím a pak mu ji jen předat
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
15
Vaše jistota na trhu IT
Výjimky kontrolované a
nekontrolované
►Hierarchie výjimek
►Pořadí výjimek v blocích catch
►Metody generující výjimky
►Metody třídy Throwable
►Zřetězené výjimky
►Převod kontrolovaných na nekontrolované
Charakteristika
► Výjimky, které jsou potomky třídy RuntimeException
nebo Error označujeme jako nekontrolované (unchecked),
protože překladač nekontroluje, zda je na ně program připraven
► Ostatní výjimky označujeme jako kontrolované (checked),
protože překladač kontroluje dodržení pravidel:
● Každá metoda, která může vyhodit kontrolovanou výjimku,
se musí k této skutečnosti veřejně přihlásit
● Každé použití metody, která může vyhodit kontrolovanou výjimku,
musí být buď uzavřeno v bloku try…catch,
nebo se volající metoda musí přihlásit k tomu,
že může také vyhodit danou kontrolovanou výjimku
► Nekontrolované výjimky ohlašují chyby v programu,
kontrolované výjimky očekávatelné situace,
na jejichž výskyt má být program připraven
a měl by na ně umět reagovat
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
17
Hierarchie výjimek
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
18
Pořadí výjimek v blocích catch
► Třída NumberFormatException
je potomkem třídy RuntimeException
try {
Syntaktická chyba,
......
na druhý blok catch nikdy nedojde
}
catch (RuntimeException e) {
.........
}
Obrácené pořadí bloků catch
catch (NumberFormatException e){
vše vyřeší
........
try {
}
......
}
catch (NumberFormatException e) {
.........
}
catch (RuntimeException e){
........
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
19
Metody generující výjimky
► Java vyžaduje, aby programy, které používají metody
schopné vyvolat kontrolované výjimky,
byly o této schopnosti používaných metod informovány =>
pak vědí, které výjimku musí umět zachytit a ošetřit
► Všechny kontrolované výjimky, které může metoda vyhodit,
musí deklarovat v hlavičce za klíčovým slovem throws
► Deklarace vyhazování nekontrolovaných výjimek není povinná
public void metoda()
throws KontrolovanáVýjimka1,
KontrolovanáVýjimka2
{
// Tělo metody
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
20
Metody třídy Throwable
► String getMessage()
Vrátí zprávu popisující danou výjimku
► String toString()
Vrátí název třídy výjimky následovaný případnou zprávou
► void printStackTrace()
Vytiskne toString() následovaný sadou informací o volající
posloupnosti, která vedla k vzniku výjimky
► Throwable fillInStackTrace()
Připraví nové informace o volací posloupnosti
vedoucí k místu zavolání této metody
► StackTraceElement[] getStackTrace()
Vrátí uchované informace o volací posloupnosti dané výjimky
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
21
Zřetězené výjimky
► V některých situacích je vhodné v rámci ošetření výjimky vyvolat
jinou výjimku, a přitom umožnit zjistit,
která výjimka byla prvotním hybatelem celé akce
► Řada výjimek má mezi svými konstruktory i takové,
které akceptují jako poslední parametr
odkaz na výjimku, jež byla příčinou vyvolání dané výjimky
► Chce-li se program zeptat výjimky na výjimku, která ji způsobila,
použije metodu
public Throwable getCause()
► Ve zprávě o vyvolání výjimky jsou místa, kde byla jedna výjimka
nahrazena jinou, označována textem caused by:
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
22
Ukázka výpisu při zřetězení výjimek
HighLevelException: MidLevelException: LowLevelException
at Junk.a(Junk.java:13)
at Junk.main(Junk.java:4)
Caused by: MidLevelException: LowLevelException
at Junk.c(Junk.java:23)
at Junk.b(Junk.java:17)
at Junk.a(Junk.java:11)
... 1 more
Caused by: LowLevelException
at Junk.e(Junk.java:30)
at Junk.d(Junk.java:27)
at Junk.c(Junk.java:21)
... 3 more
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
23
Převod kontrolovaných na nekontrolované
► Ošetřování kontrolovaných výjimek obtěžuje
► Víme-li, že k dané výjimce nejspíš nedojde
a ošetřujeme-li ji pouze proto, že na tom překladač trvá,
můžeme pro případ, že by k výjimce přece jenom došlo
zaměnit kontrolovanou výjimku za nekontrolovanou
public void prevod( String s ) {
try {
prověř( s );
} catch( Exception ex ) {
throw new RuntimeException( " Neprověřeno! ", ex );
}
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
24
Vaše jistota na trhu IT
Definice vlastních výjimek
►Hierarchie výjimek
►Pořadí výjimek v blocích catch
►Metody generující výjimky
►Metody třídy Throwable
►Vlastní výjimky
►Zásady správného používání výjimek
Definice vlastních výjimek
► Výjimky jsou zcela běžné třídy;
považujeme-li to proto za vhodné, můžeme definovat i vlastní
► Před definicí nové výjimky bychom si měli ujasnit,
bude-li kontrolovaná či nekontrolovaná;
podle toho definujeme jejího předka
► Název výjimek končí dle konvencí slovem Exception
před nímž je naznačena podstata dané výjimky
● IllegalArgumetnException
● NoSuchMethodException
● BadStringOperationException
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
26
Příklad vlastní kontrolované výjimky
public class VelkýPrůšvihException
extends Exception
{
public VelkýPrůšvihException() {};
public VelkýPrůšvihException( String zpráva ) {
super( zpráva );
}
public VelkýPrůšvihException(String zpráva,
Throwable původce ) {
super( zpráva, původce );
}
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
27
Test správného vyhození výjimky
► Na vytvářených programech je třeba otestovat i to,
že v definovaných situacích vyhodí požadovanou výjimku
public void testVyhozeníVýjimky()
{
try {
metodaKteráMáVyhoditVýjimku();
} catch ( VelkýPrůšvihException vpe ) {
return;
}
fail( "Nebyla vyhozena výjimka VelkýPrůšvihException" );
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
28
Zásady správného používání výjimek
1/2
Neignorujte
výjimky
try {
//Nějaký kód
}
catch(Exception e){}
► Výjimky, o nichž víte, že nemohou nastat,
převeďte na nekontrolované pro případ,
že by v budoucích verzích programu nastat mohly
► Při ošetřování výjimek, které nastat mohou,
ale nemají vliv na chod programu,
vložte do těla ošetření alespoň vysvětlující komentář
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
29
Zásady správného používání výjimek
2/2
► Používejte výjimky pouze k ošetření výjimečných stavů
► Kontrolované výjimky používejte u stavů, z nichž se lze zotavit,
jinak použijte výjimky nekontrolované
► Vyhýbejte se zbytečnému používání kontrolovaných výjimek
● Programátory ošetřování kontrolovaných výjimek obtěžuje
a mají pak tendenci je ošetřovat prázdným blokem catch
► Dávejte přednost standardním výjimkám,
vyvolávejte výjimky odpovídající dané abstrakci
● Programátoři by měli z názvu výjimky poznat, co se stalo
● Standardní výjimky mají všeobecně známý význam
► Snažte se o atomičnost selhání; i po vyhození výjimky
by měl být objekt v dobře definovaném stavu
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
30
Zásady správného používání výjimek
3/2
► Doplňujte výjimky zprávami,
výjimka by sama měla poskytnout dostatek informací
a neměla by programátora nutit k podrobnější analýze programu
► Dokumentujte vyvolávané výjimky v dokumentačních
komentářích pomocí značky @throws
► Nedělejte bloky try zbytečně velké,
kód uvnitř těchto bloků se neoptimalizuje
► Umíte-li výjimku v metodě ošetřit, udělejte to
► Detekuje-li se chyba v jedné metodě a má se ošetřit v jiné
(stejné či jiné instance), použijte výjimku.
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
31
Nejčastěji používané výjimky
1/2
► IllegalArgumentException
Byla zadána nepovolená hodnota parametru
● Např. chci nastavit zápornou velikost grafického tvaru
► IllegalStateException
V daném stavu objektu nelze metodu provést
● Např. otevřu soubor, přečtu pár vět, zavřu soubor a chci znovu přečíst větu
► NullPointerException
Byla vyvolána metoda instance, na níž ukazuje prázdný odkaz,
nebo byl předán nepovolený prázdný odkaz v parametru
► ArrayIndexOutOfBoundException
Byly zadány špatné meze pole, buď záporné nebo moc velké
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
32
Nejčastěji používané výjimky
2/2
► ConcurrentModificationException
V průběhu iterace byla změněna struktura kontejneru
● Např. byl do kontejneru přidán prvek
► NumberFormatException
Je požadován špatný převod řetězce na číslo či naopak
● Chci-li např. převést na číslo řetězec, který není číslem
● Častá chyba v metodách String.format či PrintStream.printf
► ClassCastException
Požadované přetypování není možné
► UnsupportedOperationException
Požadovaná operace není podporována
(např. chci přidat prvek do neměnného kontejneru)
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
33
Vaše jistota na trhu IT
Děkuji za pozornost
►Rudolf Pecinovský
http://vyuka.pecinovsky.cz/vse
mail: [email protected]
ICQ: 158 156 600
Slide 23
Vaše jistota na trhu IT
Výjimky
Rudolf Pecinovský
[email protected]
Vaše jistota na trhu IT
Obsah s odkazy
►Výjimky
►Výjimky kontrolované a nekontrolované
►Definice vlastních výjimek
Vaše jistota na trhu IT
Výjimky
►Výjimečné situace v programech
►Ošetření nestandardních situací v Javě
►Zpráva o výjimce
►Klíčová slova
►Činnost
►Vyvolání
Výjimečné situace v programech
► V každém programu je alespoň jedna chyba –
program na ni musí být připraven
► Starší programy
● Program vypsal chybové hlášení a ukončil činnost;
● V některých situacích (válcovací stolice, autopilot, …) nepřijatelné
● Funkce vrátí hodnotu signalizující chybu
● Programátor musí neustále testovat, co funkce vrací
● Knihovna měla pro tyto účely vyhrazenu speciální proměnnou,
do níž se v případě chyby zapsal její kód; nahlédnutím do proměnné
program zjistil kód poslední chyby
● Programátor musí neustále testovat, jaká je v proměnné hodnota
► Některé jazyky (Cobol, PL/1, …) proto přišly s koncepcí
ošetření nestandardních situací
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
4
Ošetření nestandardních situací v Javě
► Výjimečná událost =
problém, který brání dalšímu vykonávání části kódu
► Událost je výjimečná v tom, že na rozdíl od běžných problémů
nemá program k vyřešení situace dost informaci
► Program může při výskytu výjimečné události vyvolat výjimku
► Výjimka (exception)
objekt určený k přenosu informací o nastalém problému
z místa jeho vzniku do místa, kde bude problém řešen
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
5
Postup při vyvolání výjimky
1. Vytvoří se výjimka = objekt typu Throwable
(prakticky vždy instance některého z potomků)
2. Vytvořená výjimka se vyhodí =
přeruší se běh programu v místě, kde výjimka vznikla,
a začne se hledat místo, kde bude daná výjimka ošetřena
3. Ošetření výjimky (handler) by mělo uvést program do stavu,
v němž může jeho vykonávání pokračovat
► Výjimka „probublává“ programem z místa vyhození stále výše
a nenarazí-li cestou nikde na své ošetření,
zachytí ji virtuální stroj, který na standardní chybový výstup
vypíše zprávu o vzniku výjimky
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
6
Systémová zpráva o vzniku výjimky
Zpráva o vzniku výjimky spolu s názvem vlákna,
v němž k výjimce došlo (zde AWT-EventQueue-0)
Popis druhu výjimky (aritmetická výjimka dělení nulou)
Informace o místě, odkud byla volána metoda,
která vyvolala metodu, v níž došlo k vyhození výjimky
Informace o místě, odkud byla volána metoda,
v níž došlo k vyhození výjimky
Úplný název třídy včetně balíčku
Copyright © 2006, Rudolf Pecinovský
Název metody
VŠE – 05
Název souboru se
zdrojovým kódem
Číslo řádku zdrojáku,
kde došlo k výjimce
7
Klíčová slova související s výjimkami
► try (zkus)
Označuje blok kódu, v němž může dojít k výjimce
► throw (hoď)
Příkaz k vyhození výjimky;
musí být následován odkazem na existující instanci
► catch (chyť)
Blok ošetřující výjimku, která je zadána jako parametr
► finally (na konec)
Blok s povinnými závěrečnými akcemi nezávisejícími
na případném vzniku výjimky
► throws (hází)
Uvození seznamu výjimek vyhazovaných danou metodou
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
8
Vyvolání a ošetření výjimky v kódu
try {
//Kód, který může vyvolat výjimky
}
catch( Typ1 id1 ) {
//Ošetření výjimek typu Typ1
}
...
catch( TypN idN ) {
//ošetření výjimek typu TypN
}
finally {
//Kód, který se na závěr VŽDY provede
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
9
Náznak činnosti – řádný průběh
nedojde k vyvolání výjimky
= nedojde k chybě
try {
příkaz1();
příkaz2();
příkaz3();
}
catch ( xxxException e ) {
příkazProOšetřeníChyby();
}
Bloky catch
catch (…..
se přeskočí
finally {
ukončovacíPříkazy();
}
dalšíPříkaz();
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
12
Náznak činnosti – ošetřený výjimka
try {
příkaz1(); Při provádění metody příkaz2
dojde k ošetřené chybě
příkaz2();
příkaz3();
Byla vyhozena výjimka
tohoto typu nebo typu
}
některého z potomků
catch ( xxxException e ) {
příkazProOšetřeníChyby();
}
Ostatní bloky catch
catch (…..
se přeskočí
finally {
ukončovacíPříkazy();
}
dalšíPříkaz();
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
13
Náznak činnosti – neošetřená výjimka
Při provádění metody příkaz2
dojde k NEošetřené chybě
try {
příkaz1();
příkaz2();
příkaz3();
}
catch ( xxxException e ) {
příkazProOšetřeníChyby();
}
Ošetření nebylo nalezeno =>
catch (…..
provede se blok finally
a opouští se metoda
finally {
ukončovacíPříkazy();
}
dalšíPříkaz();
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
14
Vyvolání výjimky
public class Xyz implements Comparable
{
public bolean compareTo( Object o )
{
if( !(o instanceOf Xyz) )
throw new ClassCastException (
"\nPokus o porovnání s neporovnatelnou"
+ " instancí " + o );
//Zjištění, kdo je větší
return vysledek;
}
}
► Instanci nemusíme vytvářet až v příkazu throw,
můžeme ji vytvořit kdykoliv před tím a pak mu ji jen předat
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
15
Vaše jistota na trhu IT
Výjimky kontrolované a
nekontrolované
►Hierarchie výjimek
►Pořadí výjimek v blocích catch
►Metody generující výjimky
►Metody třídy Throwable
►Zřetězené výjimky
►Převod kontrolovaných na nekontrolované
Charakteristika
► Výjimky, které jsou potomky třídy RuntimeException
nebo Error označujeme jako nekontrolované (unchecked),
protože překladač nekontroluje, zda je na ně program připraven
► Ostatní výjimky označujeme jako kontrolované (checked),
protože překladač kontroluje dodržení pravidel:
● Každá metoda, která může vyhodit kontrolovanou výjimku,
se musí k této skutečnosti veřejně přihlásit
● Každé použití metody, která může vyhodit kontrolovanou výjimku,
musí být buď uzavřeno v bloku try…catch,
nebo se volající metoda musí přihlásit k tomu,
že může také vyhodit danou kontrolovanou výjimku
► Nekontrolované výjimky ohlašují chyby v programu,
kontrolované výjimky očekávatelné situace,
na jejichž výskyt má být program připraven
a měl by na ně umět reagovat
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
17
Hierarchie výjimek
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
18
Pořadí výjimek v blocích catch
► Třída NumberFormatException
je potomkem třídy RuntimeException
try {
Syntaktická chyba,
......
na druhý blok catch nikdy nedojde
}
catch (RuntimeException e) {
.........
}
Obrácené pořadí bloků catch
catch (NumberFormatException e){
vše vyřeší
........
try {
}
......
}
catch (NumberFormatException e) {
.........
}
catch (RuntimeException e){
........
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
19
Metody generující výjimky
► Java vyžaduje, aby programy, které používají metody
schopné vyvolat kontrolované výjimky,
byly o této schopnosti používaných metod informovány =>
pak vědí, které výjimku musí umět zachytit a ošetřit
► Všechny kontrolované výjimky, které může metoda vyhodit,
musí deklarovat v hlavičce za klíčovým slovem throws
► Deklarace vyhazování nekontrolovaných výjimek není povinná
public void metoda()
throws KontrolovanáVýjimka1,
KontrolovanáVýjimka2
{
// Tělo metody
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
20
Metody třídy Throwable
► String getMessage()
Vrátí zprávu popisující danou výjimku
► String toString()
Vrátí název třídy výjimky následovaný případnou zprávou
► void printStackTrace()
Vytiskne toString() následovaný sadou informací o volající
posloupnosti, která vedla k vzniku výjimky
► Throwable fillInStackTrace()
Připraví nové informace o volací posloupnosti
vedoucí k místu zavolání této metody
► StackTraceElement[] getStackTrace()
Vrátí uchované informace o volací posloupnosti dané výjimky
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
21
Zřetězené výjimky
► V některých situacích je vhodné v rámci ošetření výjimky vyvolat
jinou výjimku, a přitom umožnit zjistit,
která výjimka byla prvotním hybatelem celé akce
► Řada výjimek má mezi svými konstruktory i takové,
které akceptují jako poslední parametr
odkaz na výjimku, jež byla příčinou vyvolání dané výjimky
► Chce-li se program zeptat výjimky na výjimku, která ji způsobila,
použije metodu
public Throwable getCause()
► Ve zprávě o vyvolání výjimky jsou místa, kde byla jedna výjimka
nahrazena jinou, označována textem caused by:
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
22
Ukázka výpisu při zřetězení výjimek
HighLevelException: MidLevelException: LowLevelException
at Junk.a(Junk.java:13)
at Junk.main(Junk.java:4)
Caused by: MidLevelException: LowLevelException
at Junk.c(Junk.java:23)
at Junk.b(Junk.java:17)
at Junk.a(Junk.java:11)
... 1 more
Caused by: LowLevelException
at Junk.e(Junk.java:30)
at Junk.d(Junk.java:27)
at Junk.c(Junk.java:21)
... 3 more
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
23
Převod kontrolovaných na nekontrolované
► Ošetřování kontrolovaných výjimek obtěžuje
► Víme-li, že k dané výjimce nejspíš nedojde
a ošetřujeme-li ji pouze proto, že na tom překladač trvá,
můžeme pro případ, že by k výjimce přece jenom došlo
zaměnit kontrolovanou výjimku za nekontrolovanou
public void prevod( String s ) {
try {
prověř( s );
} catch( Exception ex ) {
throw new RuntimeException( " Neprověřeno! ", ex );
}
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
24
Vaše jistota na trhu IT
Definice vlastních výjimek
►Hierarchie výjimek
►Pořadí výjimek v blocích catch
►Metody generující výjimky
►Metody třídy Throwable
►Vlastní výjimky
►Zásady správného používání výjimek
Definice vlastních výjimek
► Výjimky jsou zcela běžné třídy;
považujeme-li to proto za vhodné, můžeme definovat i vlastní
► Před definicí nové výjimky bychom si měli ujasnit,
bude-li kontrolovaná či nekontrolovaná;
podle toho definujeme jejího předka
► Název výjimek končí dle konvencí slovem Exception
před nímž je naznačena podstata dané výjimky
● IllegalArgumetnException
● NoSuchMethodException
● BadStringOperationException
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
26
Příklad vlastní kontrolované výjimky
public class VelkýPrůšvihException
extends Exception
{
public VelkýPrůšvihException() {};
public VelkýPrůšvihException( String zpráva ) {
super( zpráva );
}
public VelkýPrůšvihException(String zpráva,
Throwable původce ) {
super( zpráva, původce );
}
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
27
Test správného vyhození výjimky
► Na vytvářených programech je třeba otestovat i to,
že v definovaných situacích vyhodí požadovanou výjimku
public void testVyhozeníVýjimky()
{
try {
metodaKteráMáVyhoditVýjimku();
} catch ( VelkýPrůšvihException vpe ) {
return;
}
fail( "Nebyla vyhozena výjimka VelkýPrůšvihException" );
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
28
Zásady správného používání výjimek
1/2
Neignorujte
výjimky
try {
//Nějaký kód
}
catch(Exception e){}
► Výjimky, o nichž víte, že nemohou nastat,
převeďte na nekontrolované pro případ,
že by v budoucích verzích programu nastat mohly
► Při ošetřování výjimek, které nastat mohou,
ale nemají vliv na chod programu,
vložte do těla ošetření alespoň vysvětlující komentář
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
29
Zásady správného používání výjimek
2/2
► Používejte výjimky pouze k ošetření výjimečných stavů
► Kontrolované výjimky používejte u stavů, z nichž se lze zotavit,
jinak použijte výjimky nekontrolované
► Vyhýbejte se zbytečnému používání kontrolovaných výjimek
● Programátory ošetřování kontrolovaných výjimek obtěžuje
a mají pak tendenci je ošetřovat prázdným blokem catch
► Dávejte přednost standardním výjimkám,
vyvolávejte výjimky odpovídající dané abstrakci
● Programátoři by měli z názvu výjimky poznat, co se stalo
● Standardní výjimky mají všeobecně známý význam
► Snažte se o atomičnost selhání; i po vyhození výjimky
by měl být objekt v dobře definovaném stavu
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
30
Zásady správného používání výjimek
3/2
► Doplňujte výjimky zprávami,
výjimka by sama měla poskytnout dostatek informací
a neměla by programátora nutit k podrobnější analýze programu
► Dokumentujte vyvolávané výjimky v dokumentačních
komentářích pomocí značky @throws
► Nedělejte bloky try zbytečně velké,
kód uvnitř těchto bloků se neoptimalizuje
► Umíte-li výjimku v metodě ošetřit, udělejte to
► Detekuje-li se chyba v jedné metodě a má se ošetřit v jiné
(stejné či jiné instance), použijte výjimku.
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
31
Nejčastěji používané výjimky
1/2
► IllegalArgumentException
Byla zadána nepovolená hodnota parametru
● Např. chci nastavit zápornou velikost grafického tvaru
► IllegalStateException
V daném stavu objektu nelze metodu provést
● Např. otevřu soubor, přečtu pár vět, zavřu soubor a chci znovu přečíst větu
► NullPointerException
Byla vyvolána metoda instance, na níž ukazuje prázdný odkaz,
nebo byl předán nepovolený prázdný odkaz v parametru
► ArrayIndexOutOfBoundException
Byly zadány špatné meze pole, buď záporné nebo moc velké
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
32
Nejčastěji používané výjimky
2/2
► ConcurrentModificationException
V průběhu iterace byla změněna struktura kontejneru
● Např. byl do kontejneru přidán prvek
► NumberFormatException
Je požadován špatný převod řetězce na číslo či naopak
● Chci-li např. převést na číslo řetězec, který není číslem
● Častá chyba v metodách String.format či PrintStream.printf
► ClassCastException
Požadované přetypování není možné
► UnsupportedOperationException
Požadovaná operace není podporována
(např. chci přidat prvek do neměnného kontejneru)
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
33
Vaše jistota na trhu IT
Děkuji za pozornost
►Rudolf Pecinovský
http://vyuka.pecinovsky.cz/vse
mail: [email protected]
ICQ: 158 156 600
Slide 24
Vaše jistota na trhu IT
Výjimky
Rudolf Pecinovský
[email protected]
Vaše jistota na trhu IT
Obsah s odkazy
►Výjimky
►Výjimky kontrolované a nekontrolované
►Definice vlastních výjimek
Vaše jistota na trhu IT
Výjimky
►Výjimečné situace v programech
►Ošetření nestandardních situací v Javě
►Zpráva o výjimce
►Klíčová slova
►Činnost
►Vyvolání
Výjimečné situace v programech
► V každém programu je alespoň jedna chyba –
program na ni musí být připraven
► Starší programy
● Program vypsal chybové hlášení a ukončil činnost;
● V některých situacích (válcovací stolice, autopilot, …) nepřijatelné
● Funkce vrátí hodnotu signalizující chybu
● Programátor musí neustále testovat, co funkce vrací
● Knihovna měla pro tyto účely vyhrazenu speciální proměnnou,
do níž se v případě chyby zapsal její kód; nahlédnutím do proměnné
program zjistil kód poslední chyby
● Programátor musí neustále testovat, jaká je v proměnné hodnota
► Některé jazyky (Cobol, PL/1, …) proto přišly s koncepcí
ošetření nestandardních situací
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
4
Ošetření nestandardních situací v Javě
► Výjimečná událost =
problém, který brání dalšímu vykonávání části kódu
► Událost je výjimečná v tom, že na rozdíl od běžných problémů
nemá program k vyřešení situace dost informaci
► Program může při výskytu výjimečné události vyvolat výjimku
► Výjimka (exception)
objekt určený k přenosu informací o nastalém problému
z místa jeho vzniku do místa, kde bude problém řešen
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
5
Postup při vyvolání výjimky
1. Vytvoří se výjimka = objekt typu Throwable
(prakticky vždy instance některého z potomků)
2. Vytvořená výjimka se vyhodí =
přeruší se běh programu v místě, kde výjimka vznikla,
a začne se hledat místo, kde bude daná výjimka ošetřena
3. Ošetření výjimky (handler) by mělo uvést program do stavu,
v němž může jeho vykonávání pokračovat
► Výjimka „probublává“ programem z místa vyhození stále výše
a nenarazí-li cestou nikde na své ošetření,
zachytí ji virtuální stroj, který na standardní chybový výstup
vypíše zprávu o vzniku výjimky
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
6
Systémová zpráva o vzniku výjimky
Zpráva o vzniku výjimky spolu s názvem vlákna,
v němž k výjimce došlo (zde AWT-EventQueue-0)
Popis druhu výjimky (aritmetická výjimka dělení nulou)
Informace o místě, odkud byla volána metoda,
která vyvolala metodu, v níž došlo k vyhození výjimky
Informace o místě, odkud byla volána metoda,
v níž došlo k vyhození výjimky
Úplný název třídy včetně balíčku
Copyright © 2006, Rudolf Pecinovský
Název metody
VŠE – 05
Název souboru se
zdrojovým kódem
Číslo řádku zdrojáku,
kde došlo k výjimce
7
Klíčová slova související s výjimkami
► try (zkus)
Označuje blok kódu, v němž může dojít k výjimce
► throw (hoď)
Příkaz k vyhození výjimky;
musí být následován odkazem na existující instanci
► catch (chyť)
Blok ošetřující výjimku, která je zadána jako parametr
► finally (na konec)
Blok s povinnými závěrečnými akcemi nezávisejícími
na případném vzniku výjimky
► throws (hází)
Uvození seznamu výjimek vyhazovaných danou metodou
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
8
Vyvolání a ošetření výjimky v kódu
try {
//Kód, který může vyvolat výjimky
}
catch( Typ1 id1 ) {
//Ošetření výjimek typu Typ1
}
...
catch( TypN idN ) {
//ošetření výjimek typu TypN
}
finally {
//Kód, který se na závěr VŽDY provede
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
9
Náznak činnosti – řádný průběh
nedojde k vyvolání výjimky
= nedojde k chybě
try {
příkaz1();
příkaz2();
příkaz3();
}
catch ( xxxException e ) {
příkazProOšetřeníChyby();
}
Bloky catch
catch (…..
se přeskočí
finally {
ukončovacíPříkazy();
}
dalšíPříkaz();
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
12
Náznak činnosti – ošetřený výjimka
try {
příkaz1(); Při provádění metody příkaz2
dojde k ošetřené chybě
příkaz2();
příkaz3();
Byla vyhozena výjimka
tohoto typu nebo typu
}
některého z potomků
catch ( xxxException e ) {
příkazProOšetřeníChyby();
}
Ostatní bloky catch
catch (…..
se přeskočí
finally {
ukončovacíPříkazy();
}
dalšíPříkaz();
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
13
Náznak činnosti – neošetřená výjimka
Při provádění metody příkaz2
dojde k NEošetřené chybě
try {
příkaz1();
příkaz2();
příkaz3();
}
catch ( xxxException e ) {
příkazProOšetřeníChyby();
}
Ošetření nebylo nalezeno =>
catch (…..
provede se blok finally
a opouští se metoda
finally {
ukončovacíPříkazy();
}
dalšíPříkaz();
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
14
Vyvolání výjimky
public class Xyz implements Comparable
{
public bolean compareTo( Object o )
{
if( !(o instanceOf Xyz) )
throw new ClassCastException (
"\nPokus o porovnání s neporovnatelnou"
+ " instancí " + o );
//Zjištění, kdo je větší
return vysledek;
}
}
► Instanci nemusíme vytvářet až v příkazu throw,
můžeme ji vytvořit kdykoliv před tím a pak mu ji jen předat
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
15
Vaše jistota na trhu IT
Výjimky kontrolované a
nekontrolované
►Hierarchie výjimek
►Pořadí výjimek v blocích catch
►Metody generující výjimky
►Metody třídy Throwable
►Zřetězené výjimky
►Převod kontrolovaných na nekontrolované
Charakteristika
► Výjimky, které jsou potomky třídy RuntimeException
nebo Error označujeme jako nekontrolované (unchecked),
protože překladač nekontroluje, zda je na ně program připraven
► Ostatní výjimky označujeme jako kontrolované (checked),
protože překladač kontroluje dodržení pravidel:
● Každá metoda, která může vyhodit kontrolovanou výjimku,
se musí k této skutečnosti veřejně přihlásit
● Každé použití metody, která může vyhodit kontrolovanou výjimku,
musí být buď uzavřeno v bloku try…catch,
nebo se volající metoda musí přihlásit k tomu,
že může také vyhodit danou kontrolovanou výjimku
► Nekontrolované výjimky ohlašují chyby v programu,
kontrolované výjimky očekávatelné situace,
na jejichž výskyt má být program připraven
a měl by na ně umět reagovat
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
17
Hierarchie výjimek
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
18
Pořadí výjimek v blocích catch
► Třída NumberFormatException
je potomkem třídy RuntimeException
try {
Syntaktická chyba,
......
na druhý blok catch nikdy nedojde
}
catch (RuntimeException e) {
.........
}
Obrácené pořadí bloků catch
catch (NumberFormatException e){
vše vyřeší
........
try {
}
......
}
catch (NumberFormatException e) {
.........
}
catch (RuntimeException e){
........
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
19
Metody generující výjimky
► Java vyžaduje, aby programy, které používají metody
schopné vyvolat kontrolované výjimky,
byly o této schopnosti používaných metod informovány =>
pak vědí, které výjimku musí umět zachytit a ošetřit
► Všechny kontrolované výjimky, které může metoda vyhodit,
musí deklarovat v hlavičce za klíčovým slovem throws
► Deklarace vyhazování nekontrolovaných výjimek není povinná
public void metoda()
throws KontrolovanáVýjimka1,
KontrolovanáVýjimka2
{
// Tělo metody
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
20
Metody třídy Throwable
► String getMessage()
Vrátí zprávu popisující danou výjimku
► String toString()
Vrátí název třídy výjimky následovaný případnou zprávou
► void printStackTrace()
Vytiskne toString() následovaný sadou informací o volající
posloupnosti, která vedla k vzniku výjimky
► Throwable fillInStackTrace()
Připraví nové informace o volací posloupnosti
vedoucí k místu zavolání této metody
► StackTraceElement[] getStackTrace()
Vrátí uchované informace o volací posloupnosti dané výjimky
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
21
Zřetězené výjimky
► V některých situacích je vhodné v rámci ošetření výjimky vyvolat
jinou výjimku, a přitom umožnit zjistit,
která výjimka byla prvotním hybatelem celé akce
► Řada výjimek má mezi svými konstruktory i takové,
které akceptují jako poslední parametr
odkaz na výjimku, jež byla příčinou vyvolání dané výjimky
► Chce-li se program zeptat výjimky na výjimku, která ji způsobila,
použije metodu
public Throwable getCause()
► Ve zprávě o vyvolání výjimky jsou místa, kde byla jedna výjimka
nahrazena jinou, označována textem caused by:
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
22
Ukázka výpisu při zřetězení výjimek
HighLevelException: MidLevelException: LowLevelException
at Junk.a(Junk.java:13)
at Junk.main(Junk.java:4)
Caused by: MidLevelException: LowLevelException
at Junk.c(Junk.java:23)
at Junk.b(Junk.java:17)
at Junk.a(Junk.java:11)
... 1 more
Caused by: LowLevelException
at Junk.e(Junk.java:30)
at Junk.d(Junk.java:27)
at Junk.c(Junk.java:21)
... 3 more
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
23
Převod kontrolovaných na nekontrolované
► Ošetřování kontrolovaných výjimek obtěžuje
► Víme-li, že k dané výjimce nejspíš nedojde
a ošetřujeme-li ji pouze proto, že na tom překladač trvá,
můžeme pro případ, že by k výjimce přece jenom došlo
zaměnit kontrolovanou výjimku za nekontrolovanou
public void prevod( String s ) {
try {
prověř( s );
} catch( Exception ex ) {
throw new RuntimeException( " Neprověřeno! ", ex );
}
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
24
Vaše jistota na trhu IT
Definice vlastních výjimek
►Hierarchie výjimek
►Pořadí výjimek v blocích catch
►Metody generující výjimky
►Metody třídy Throwable
►Vlastní výjimky
►Zásady správného používání výjimek
Definice vlastních výjimek
► Výjimky jsou zcela běžné třídy;
považujeme-li to proto za vhodné, můžeme definovat i vlastní
► Před definicí nové výjimky bychom si měli ujasnit,
bude-li kontrolovaná či nekontrolovaná;
podle toho definujeme jejího předka
► Název výjimek končí dle konvencí slovem Exception
před nímž je naznačena podstata dané výjimky
● IllegalArgumetnException
● NoSuchMethodException
● BadStringOperationException
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
26
Příklad vlastní kontrolované výjimky
public class VelkýPrůšvihException
extends Exception
{
public VelkýPrůšvihException() {};
public VelkýPrůšvihException( String zpráva ) {
super( zpráva );
}
public VelkýPrůšvihException(String zpráva,
Throwable původce ) {
super( zpráva, původce );
}
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
27
Test správného vyhození výjimky
► Na vytvářených programech je třeba otestovat i to,
že v definovaných situacích vyhodí požadovanou výjimku
public void testVyhozeníVýjimky()
{
try {
metodaKteráMáVyhoditVýjimku();
} catch ( VelkýPrůšvihException vpe ) {
return;
}
fail( "Nebyla vyhozena výjimka VelkýPrůšvihException" );
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
28
Zásady správného používání výjimek
1/2
Neignorujte
výjimky
try {
//Nějaký kód
}
catch(Exception e){}
► Výjimky, o nichž víte, že nemohou nastat,
převeďte na nekontrolované pro případ,
že by v budoucích verzích programu nastat mohly
► Při ošetřování výjimek, které nastat mohou,
ale nemají vliv na chod programu,
vložte do těla ošetření alespoň vysvětlující komentář
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
29
Zásady správného používání výjimek
2/2
► Používejte výjimky pouze k ošetření výjimečných stavů
► Kontrolované výjimky používejte u stavů, z nichž se lze zotavit,
jinak použijte výjimky nekontrolované
► Vyhýbejte se zbytečnému používání kontrolovaných výjimek
● Programátory ošetřování kontrolovaných výjimek obtěžuje
a mají pak tendenci je ošetřovat prázdným blokem catch
► Dávejte přednost standardním výjimkám,
vyvolávejte výjimky odpovídající dané abstrakci
● Programátoři by měli z názvu výjimky poznat, co se stalo
● Standardní výjimky mají všeobecně známý význam
► Snažte se o atomičnost selhání; i po vyhození výjimky
by měl být objekt v dobře definovaném stavu
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
30
Zásady správného používání výjimek
3/2
► Doplňujte výjimky zprávami,
výjimka by sama měla poskytnout dostatek informací
a neměla by programátora nutit k podrobnější analýze programu
► Dokumentujte vyvolávané výjimky v dokumentačních
komentářích pomocí značky @throws
► Nedělejte bloky try zbytečně velké,
kód uvnitř těchto bloků se neoptimalizuje
► Umíte-li výjimku v metodě ošetřit, udělejte to
► Detekuje-li se chyba v jedné metodě a má se ošetřit v jiné
(stejné či jiné instance), použijte výjimku.
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
31
Nejčastěji používané výjimky
1/2
► IllegalArgumentException
Byla zadána nepovolená hodnota parametru
● Např. chci nastavit zápornou velikost grafického tvaru
► IllegalStateException
V daném stavu objektu nelze metodu provést
● Např. otevřu soubor, přečtu pár vět, zavřu soubor a chci znovu přečíst větu
► NullPointerException
Byla vyvolána metoda instance, na níž ukazuje prázdný odkaz,
nebo byl předán nepovolený prázdný odkaz v parametru
► ArrayIndexOutOfBoundException
Byly zadány špatné meze pole, buď záporné nebo moc velké
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
32
Nejčastěji používané výjimky
2/2
► ConcurrentModificationException
V průběhu iterace byla změněna struktura kontejneru
● Např. byl do kontejneru přidán prvek
► NumberFormatException
Je požadován špatný převod řetězce na číslo či naopak
● Chci-li např. převést na číslo řetězec, který není číslem
● Častá chyba v metodách String.format či PrintStream.printf
► ClassCastException
Požadované přetypování není možné
► UnsupportedOperationException
Požadovaná operace není podporována
(např. chci přidat prvek do neměnného kontejneru)
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
33
Vaše jistota na trhu IT
Děkuji za pozornost
►Rudolf Pecinovský
http://vyuka.pecinovsky.cz/vse
mail: [email protected]
ICQ: 158 156 600
Slide 25
Vaše jistota na trhu IT
Výjimky
Rudolf Pecinovský
[email protected]
Vaše jistota na trhu IT
Obsah s odkazy
►Výjimky
►Výjimky kontrolované a nekontrolované
►Definice vlastních výjimek
Vaše jistota na trhu IT
Výjimky
►Výjimečné situace v programech
►Ošetření nestandardních situací v Javě
►Zpráva o výjimce
►Klíčová slova
►Činnost
►Vyvolání
Výjimečné situace v programech
► V každém programu je alespoň jedna chyba –
program na ni musí být připraven
► Starší programy
● Program vypsal chybové hlášení a ukončil činnost;
● V některých situacích (válcovací stolice, autopilot, …) nepřijatelné
● Funkce vrátí hodnotu signalizující chybu
● Programátor musí neustále testovat, co funkce vrací
● Knihovna měla pro tyto účely vyhrazenu speciální proměnnou,
do níž se v případě chyby zapsal její kód; nahlédnutím do proměnné
program zjistil kód poslední chyby
● Programátor musí neustále testovat, jaká je v proměnné hodnota
► Některé jazyky (Cobol, PL/1, …) proto přišly s koncepcí
ošetření nestandardních situací
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
4
Ošetření nestandardních situací v Javě
► Výjimečná událost =
problém, který brání dalšímu vykonávání části kódu
► Událost je výjimečná v tom, že na rozdíl od běžných problémů
nemá program k vyřešení situace dost informaci
► Program může při výskytu výjimečné události vyvolat výjimku
► Výjimka (exception)
objekt určený k přenosu informací o nastalém problému
z místa jeho vzniku do místa, kde bude problém řešen
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
5
Postup při vyvolání výjimky
1. Vytvoří se výjimka = objekt typu Throwable
(prakticky vždy instance některého z potomků)
2. Vytvořená výjimka se vyhodí =
přeruší se běh programu v místě, kde výjimka vznikla,
a začne se hledat místo, kde bude daná výjimka ošetřena
3. Ošetření výjimky (handler) by mělo uvést program do stavu,
v němž může jeho vykonávání pokračovat
► Výjimka „probublává“ programem z místa vyhození stále výše
a nenarazí-li cestou nikde na své ošetření,
zachytí ji virtuální stroj, který na standardní chybový výstup
vypíše zprávu o vzniku výjimky
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
6
Systémová zpráva o vzniku výjimky
Zpráva o vzniku výjimky spolu s názvem vlákna,
v němž k výjimce došlo (zde AWT-EventQueue-0)
Popis druhu výjimky (aritmetická výjimka dělení nulou)
Informace o místě, odkud byla volána metoda,
která vyvolala metodu, v níž došlo k vyhození výjimky
Informace o místě, odkud byla volána metoda,
v níž došlo k vyhození výjimky
Úplný název třídy včetně balíčku
Copyright © 2006, Rudolf Pecinovský
Název metody
VŠE – 05
Název souboru se
zdrojovým kódem
Číslo řádku zdrojáku,
kde došlo k výjimce
7
Klíčová slova související s výjimkami
► try (zkus)
Označuje blok kódu, v němž může dojít k výjimce
► throw (hoď)
Příkaz k vyhození výjimky;
musí být následován odkazem na existující instanci
► catch (chyť)
Blok ošetřující výjimku, která je zadána jako parametr
► finally (na konec)
Blok s povinnými závěrečnými akcemi nezávisejícími
na případném vzniku výjimky
► throws (hází)
Uvození seznamu výjimek vyhazovaných danou metodou
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
8
Vyvolání a ošetření výjimky v kódu
try {
//Kód, který může vyvolat výjimky
}
catch( Typ1 id1 ) {
//Ošetření výjimek typu Typ1
}
...
catch( TypN idN ) {
//ošetření výjimek typu TypN
}
finally {
//Kód, který se na závěr VŽDY provede
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
9
Náznak činnosti – řádný průběh
nedojde k vyvolání výjimky
= nedojde k chybě
try {
příkaz1();
příkaz2();
příkaz3();
}
catch ( xxxException e ) {
příkazProOšetřeníChyby();
}
Bloky catch
catch (…..
se přeskočí
finally {
ukončovacíPříkazy();
}
dalšíPříkaz();
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
12
Náznak činnosti – ošetřený výjimka
try {
příkaz1(); Při provádění metody příkaz2
dojde k ošetřené chybě
příkaz2();
příkaz3();
Byla vyhozena výjimka
tohoto typu nebo typu
}
některého z potomků
catch ( xxxException e ) {
příkazProOšetřeníChyby();
}
Ostatní bloky catch
catch (…..
se přeskočí
finally {
ukončovacíPříkazy();
}
dalšíPříkaz();
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
13
Náznak činnosti – neošetřená výjimka
Při provádění metody příkaz2
dojde k NEošetřené chybě
try {
příkaz1();
příkaz2();
příkaz3();
}
catch ( xxxException e ) {
příkazProOšetřeníChyby();
}
Ošetření nebylo nalezeno =>
catch (…..
provede se blok finally
a opouští se metoda
finally {
ukončovacíPříkazy();
}
dalšíPříkaz();
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
14
Vyvolání výjimky
public class Xyz implements Comparable
{
public bolean compareTo( Object o )
{
if( !(o instanceOf Xyz) )
throw new ClassCastException (
"\nPokus o porovnání s neporovnatelnou"
+ " instancí " + o );
//Zjištění, kdo je větší
return vysledek;
}
}
► Instanci nemusíme vytvářet až v příkazu throw,
můžeme ji vytvořit kdykoliv před tím a pak mu ji jen předat
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
15
Vaše jistota na trhu IT
Výjimky kontrolované a
nekontrolované
►Hierarchie výjimek
►Pořadí výjimek v blocích catch
►Metody generující výjimky
►Metody třídy Throwable
►Zřetězené výjimky
►Převod kontrolovaných na nekontrolované
Charakteristika
► Výjimky, které jsou potomky třídy RuntimeException
nebo Error označujeme jako nekontrolované (unchecked),
protože překladač nekontroluje, zda je na ně program připraven
► Ostatní výjimky označujeme jako kontrolované (checked),
protože překladač kontroluje dodržení pravidel:
● Každá metoda, která může vyhodit kontrolovanou výjimku,
se musí k této skutečnosti veřejně přihlásit
● Každé použití metody, která může vyhodit kontrolovanou výjimku,
musí být buď uzavřeno v bloku try…catch,
nebo se volající metoda musí přihlásit k tomu,
že může také vyhodit danou kontrolovanou výjimku
► Nekontrolované výjimky ohlašují chyby v programu,
kontrolované výjimky očekávatelné situace,
na jejichž výskyt má být program připraven
a měl by na ně umět reagovat
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
17
Hierarchie výjimek
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
18
Pořadí výjimek v blocích catch
► Třída NumberFormatException
je potomkem třídy RuntimeException
try {
Syntaktická chyba,
......
na druhý blok catch nikdy nedojde
}
catch (RuntimeException e) {
.........
}
Obrácené pořadí bloků catch
catch (NumberFormatException e){
vše vyřeší
........
try {
}
......
}
catch (NumberFormatException e) {
.........
}
catch (RuntimeException e){
........
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
19
Metody generující výjimky
► Java vyžaduje, aby programy, které používají metody
schopné vyvolat kontrolované výjimky,
byly o této schopnosti používaných metod informovány =>
pak vědí, které výjimku musí umět zachytit a ošetřit
► Všechny kontrolované výjimky, které může metoda vyhodit,
musí deklarovat v hlavičce za klíčovým slovem throws
► Deklarace vyhazování nekontrolovaných výjimek není povinná
public void metoda()
throws KontrolovanáVýjimka1,
KontrolovanáVýjimka2
{
// Tělo metody
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
20
Metody třídy Throwable
► String getMessage()
Vrátí zprávu popisující danou výjimku
► String toString()
Vrátí název třídy výjimky následovaný případnou zprávou
► void printStackTrace()
Vytiskne toString() následovaný sadou informací o volající
posloupnosti, která vedla k vzniku výjimky
► Throwable fillInStackTrace()
Připraví nové informace o volací posloupnosti
vedoucí k místu zavolání této metody
► StackTraceElement[] getStackTrace()
Vrátí uchované informace o volací posloupnosti dané výjimky
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
21
Zřetězené výjimky
► V některých situacích je vhodné v rámci ošetření výjimky vyvolat
jinou výjimku, a přitom umožnit zjistit,
která výjimka byla prvotním hybatelem celé akce
► Řada výjimek má mezi svými konstruktory i takové,
které akceptují jako poslední parametr
odkaz na výjimku, jež byla příčinou vyvolání dané výjimky
► Chce-li se program zeptat výjimky na výjimku, která ji způsobila,
použije metodu
public Throwable getCause()
► Ve zprávě o vyvolání výjimky jsou místa, kde byla jedna výjimka
nahrazena jinou, označována textem caused by:
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
22
Ukázka výpisu při zřetězení výjimek
HighLevelException: MidLevelException: LowLevelException
at Junk.a(Junk.java:13)
at Junk.main(Junk.java:4)
Caused by: MidLevelException: LowLevelException
at Junk.c(Junk.java:23)
at Junk.b(Junk.java:17)
at Junk.a(Junk.java:11)
... 1 more
Caused by: LowLevelException
at Junk.e(Junk.java:30)
at Junk.d(Junk.java:27)
at Junk.c(Junk.java:21)
... 3 more
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
23
Převod kontrolovaných na nekontrolované
► Ošetřování kontrolovaných výjimek obtěžuje
► Víme-li, že k dané výjimce nejspíš nedojde
a ošetřujeme-li ji pouze proto, že na tom překladač trvá,
můžeme pro případ, že by k výjimce přece jenom došlo
zaměnit kontrolovanou výjimku za nekontrolovanou
public void prevod( String s ) {
try {
prověř( s );
} catch( Exception ex ) {
throw new RuntimeException( " Neprověřeno! ", ex );
}
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
24
Vaše jistota na trhu IT
Definice vlastních výjimek
►Hierarchie výjimek
►Pořadí výjimek v blocích catch
►Metody generující výjimky
►Metody třídy Throwable
►Vlastní výjimky
►Zásady správného používání výjimek
Definice vlastních výjimek
► Výjimky jsou zcela běžné třídy;
považujeme-li to proto za vhodné, můžeme definovat i vlastní
► Před definicí nové výjimky bychom si měli ujasnit,
bude-li kontrolovaná či nekontrolovaná;
podle toho definujeme jejího předka
► Název výjimek končí dle konvencí slovem Exception
před nímž je naznačena podstata dané výjimky
● IllegalArgumetnException
● NoSuchMethodException
● BadStringOperationException
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
26
Příklad vlastní kontrolované výjimky
public class VelkýPrůšvihException
extends Exception
{
public VelkýPrůšvihException() {};
public VelkýPrůšvihException( String zpráva ) {
super( zpráva );
}
public VelkýPrůšvihException(String zpráva,
Throwable původce ) {
super( zpráva, původce );
}
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
27
Test správného vyhození výjimky
► Na vytvářených programech je třeba otestovat i to,
že v definovaných situacích vyhodí požadovanou výjimku
public void testVyhozeníVýjimky()
{
try {
metodaKteráMáVyhoditVýjimku();
} catch ( VelkýPrůšvihException vpe ) {
return;
}
fail( "Nebyla vyhozena výjimka VelkýPrůšvihException" );
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
28
Zásady správného používání výjimek
1/2
Neignorujte
výjimky
try {
//Nějaký kód
}
catch(Exception e){}
► Výjimky, o nichž víte, že nemohou nastat,
převeďte na nekontrolované pro případ,
že by v budoucích verzích programu nastat mohly
► Při ošetřování výjimek, které nastat mohou,
ale nemají vliv na chod programu,
vložte do těla ošetření alespoň vysvětlující komentář
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
29
Zásady správného používání výjimek
2/2
► Používejte výjimky pouze k ošetření výjimečných stavů
► Kontrolované výjimky používejte u stavů, z nichž se lze zotavit,
jinak použijte výjimky nekontrolované
► Vyhýbejte se zbytečnému používání kontrolovaných výjimek
● Programátory ošetřování kontrolovaných výjimek obtěžuje
a mají pak tendenci je ošetřovat prázdným blokem catch
► Dávejte přednost standardním výjimkám,
vyvolávejte výjimky odpovídající dané abstrakci
● Programátoři by měli z názvu výjimky poznat, co se stalo
● Standardní výjimky mají všeobecně známý význam
► Snažte se o atomičnost selhání; i po vyhození výjimky
by měl být objekt v dobře definovaném stavu
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
30
Zásady správného používání výjimek
3/2
► Doplňujte výjimky zprávami,
výjimka by sama měla poskytnout dostatek informací
a neměla by programátora nutit k podrobnější analýze programu
► Dokumentujte vyvolávané výjimky v dokumentačních
komentářích pomocí značky @throws
► Nedělejte bloky try zbytečně velké,
kód uvnitř těchto bloků se neoptimalizuje
► Umíte-li výjimku v metodě ošetřit, udělejte to
► Detekuje-li se chyba v jedné metodě a má se ošetřit v jiné
(stejné či jiné instance), použijte výjimku.
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
31
Nejčastěji používané výjimky
1/2
► IllegalArgumentException
Byla zadána nepovolená hodnota parametru
● Např. chci nastavit zápornou velikost grafického tvaru
► IllegalStateException
V daném stavu objektu nelze metodu provést
● Např. otevřu soubor, přečtu pár vět, zavřu soubor a chci znovu přečíst větu
► NullPointerException
Byla vyvolána metoda instance, na níž ukazuje prázdný odkaz,
nebo byl předán nepovolený prázdný odkaz v parametru
► ArrayIndexOutOfBoundException
Byly zadány špatné meze pole, buď záporné nebo moc velké
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
32
Nejčastěji používané výjimky
2/2
► ConcurrentModificationException
V průběhu iterace byla změněna struktura kontejneru
● Např. byl do kontejneru přidán prvek
► NumberFormatException
Je požadován špatný převod řetězce na číslo či naopak
● Chci-li např. převést na číslo řetězec, který není číslem
● Častá chyba v metodách String.format či PrintStream.printf
► ClassCastException
Požadované přetypování není možné
► UnsupportedOperationException
Požadovaná operace není podporována
(např. chci přidat prvek do neměnného kontejneru)
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
33
Vaše jistota na trhu IT
Děkuji za pozornost
►Rudolf Pecinovský
http://vyuka.pecinovsky.cz/vse
mail: [email protected]
ICQ: 158 156 600
Slide 26
Vaše jistota na trhu IT
Výjimky
Rudolf Pecinovský
[email protected]
Vaše jistota na trhu IT
Obsah s odkazy
►Výjimky
►Výjimky kontrolované a nekontrolované
►Definice vlastních výjimek
Vaše jistota na trhu IT
Výjimky
►Výjimečné situace v programech
►Ošetření nestandardních situací v Javě
►Zpráva o výjimce
►Klíčová slova
►Činnost
►Vyvolání
Výjimečné situace v programech
► V každém programu je alespoň jedna chyba –
program na ni musí být připraven
► Starší programy
● Program vypsal chybové hlášení a ukončil činnost;
● V některých situacích (válcovací stolice, autopilot, …) nepřijatelné
● Funkce vrátí hodnotu signalizující chybu
● Programátor musí neustále testovat, co funkce vrací
● Knihovna měla pro tyto účely vyhrazenu speciální proměnnou,
do níž se v případě chyby zapsal její kód; nahlédnutím do proměnné
program zjistil kód poslední chyby
● Programátor musí neustále testovat, jaká je v proměnné hodnota
► Některé jazyky (Cobol, PL/1, …) proto přišly s koncepcí
ošetření nestandardních situací
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
4
Ošetření nestandardních situací v Javě
► Výjimečná událost =
problém, který brání dalšímu vykonávání části kódu
► Událost je výjimečná v tom, že na rozdíl od běžných problémů
nemá program k vyřešení situace dost informaci
► Program může při výskytu výjimečné události vyvolat výjimku
► Výjimka (exception)
objekt určený k přenosu informací o nastalém problému
z místa jeho vzniku do místa, kde bude problém řešen
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
5
Postup při vyvolání výjimky
1. Vytvoří se výjimka = objekt typu Throwable
(prakticky vždy instance některého z potomků)
2. Vytvořená výjimka se vyhodí =
přeruší se běh programu v místě, kde výjimka vznikla,
a začne se hledat místo, kde bude daná výjimka ošetřena
3. Ošetření výjimky (handler) by mělo uvést program do stavu,
v němž může jeho vykonávání pokračovat
► Výjimka „probublává“ programem z místa vyhození stále výše
a nenarazí-li cestou nikde na své ošetření,
zachytí ji virtuální stroj, který na standardní chybový výstup
vypíše zprávu o vzniku výjimky
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
6
Systémová zpráva o vzniku výjimky
Zpráva o vzniku výjimky spolu s názvem vlákna,
v němž k výjimce došlo (zde AWT-EventQueue-0)
Popis druhu výjimky (aritmetická výjimka dělení nulou)
Informace o místě, odkud byla volána metoda,
která vyvolala metodu, v níž došlo k vyhození výjimky
Informace o místě, odkud byla volána metoda,
v níž došlo k vyhození výjimky
Úplný název třídy včetně balíčku
Copyright © 2006, Rudolf Pecinovský
Název metody
VŠE – 05
Název souboru se
zdrojovým kódem
Číslo řádku zdrojáku,
kde došlo k výjimce
7
Klíčová slova související s výjimkami
► try (zkus)
Označuje blok kódu, v němž může dojít k výjimce
► throw (hoď)
Příkaz k vyhození výjimky;
musí být následován odkazem na existující instanci
► catch (chyť)
Blok ošetřující výjimku, která je zadána jako parametr
► finally (na konec)
Blok s povinnými závěrečnými akcemi nezávisejícími
na případném vzniku výjimky
► throws (hází)
Uvození seznamu výjimek vyhazovaných danou metodou
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
8
Vyvolání a ošetření výjimky v kódu
try {
//Kód, který může vyvolat výjimky
}
catch( Typ1 id1 ) {
//Ošetření výjimek typu Typ1
}
...
catch( TypN idN ) {
//ošetření výjimek typu TypN
}
finally {
//Kód, který se na závěr VŽDY provede
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
9
Náznak činnosti – řádný průběh
nedojde k vyvolání výjimky
= nedojde k chybě
try {
příkaz1();
příkaz2();
příkaz3();
}
catch ( xxxException e ) {
příkazProOšetřeníChyby();
}
Bloky catch
catch (…..
se přeskočí
finally {
ukončovacíPříkazy();
}
dalšíPříkaz();
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
12
Náznak činnosti – ošetřený výjimka
try {
příkaz1(); Při provádění metody příkaz2
dojde k ošetřené chybě
příkaz2();
příkaz3();
Byla vyhozena výjimka
tohoto typu nebo typu
}
některého z potomků
catch ( xxxException e ) {
příkazProOšetřeníChyby();
}
Ostatní bloky catch
catch (…..
se přeskočí
finally {
ukončovacíPříkazy();
}
dalšíPříkaz();
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
13
Náznak činnosti – neošetřená výjimka
Při provádění metody příkaz2
dojde k NEošetřené chybě
try {
příkaz1();
příkaz2();
příkaz3();
}
catch ( xxxException e ) {
příkazProOšetřeníChyby();
}
Ošetření nebylo nalezeno =>
catch (…..
provede se blok finally
a opouští se metoda
finally {
ukončovacíPříkazy();
}
dalšíPříkaz();
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
14
Vyvolání výjimky
public class Xyz implements Comparable
{
public bolean compareTo( Object o )
{
if( !(o instanceOf Xyz) )
throw new ClassCastException (
"\nPokus o porovnání s neporovnatelnou"
+ " instancí " + o );
//Zjištění, kdo je větší
return vysledek;
}
}
► Instanci nemusíme vytvářet až v příkazu throw,
můžeme ji vytvořit kdykoliv před tím a pak mu ji jen předat
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
15
Vaše jistota na trhu IT
Výjimky kontrolované a
nekontrolované
►Hierarchie výjimek
►Pořadí výjimek v blocích catch
►Metody generující výjimky
►Metody třídy Throwable
►Zřetězené výjimky
►Převod kontrolovaných na nekontrolované
Charakteristika
► Výjimky, které jsou potomky třídy RuntimeException
nebo Error označujeme jako nekontrolované (unchecked),
protože překladač nekontroluje, zda je na ně program připraven
► Ostatní výjimky označujeme jako kontrolované (checked),
protože překladač kontroluje dodržení pravidel:
● Každá metoda, která může vyhodit kontrolovanou výjimku,
se musí k této skutečnosti veřejně přihlásit
● Každé použití metody, která může vyhodit kontrolovanou výjimku,
musí být buď uzavřeno v bloku try…catch,
nebo se volající metoda musí přihlásit k tomu,
že může také vyhodit danou kontrolovanou výjimku
► Nekontrolované výjimky ohlašují chyby v programu,
kontrolované výjimky očekávatelné situace,
na jejichž výskyt má být program připraven
a měl by na ně umět reagovat
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
17
Hierarchie výjimek
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
18
Pořadí výjimek v blocích catch
► Třída NumberFormatException
je potomkem třídy RuntimeException
try {
Syntaktická chyba,
......
na druhý blok catch nikdy nedojde
}
catch (RuntimeException e) {
.........
}
Obrácené pořadí bloků catch
catch (NumberFormatException e){
vše vyřeší
........
try {
}
......
}
catch (NumberFormatException e) {
.........
}
catch (RuntimeException e){
........
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
19
Metody generující výjimky
► Java vyžaduje, aby programy, které používají metody
schopné vyvolat kontrolované výjimky,
byly o této schopnosti používaných metod informovány =>
pak vědí, které výjimku musí umět zachytit a ošetřit
► Všechny kontrolované výjimky, které může metoda vyhodit,
musí deklarovat v hlavičce za klíčovým slovem throws
► Deklarace vyhazování nekontrolovaných výjimek není povinná
public void metoda()
throws KontrolovanáVýjimka1,
KontrolovanáVýjimka2
{
// Tělo metody
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
20
Metody třídy Throwable
► String getMessage()
Vrátí zprávu popisující danou výjimku
► String toString()
Vrátí název třídy výjimky následovaný případnou zprávou
► void printStackTrace()
Vytiskne toString() následovaný sadou informací o volající
posloupnosti, která vedla k vzniku výjimky
► Throwable fillInStackTrace()
Připraví nové informace o volací posloupnosti
vedoucí k místu zavolání této metody
► StackTraceElement[] getStackTrace()
Vrátí uchované informace o volací posloupnosti dané výjimky
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
21
Zřetězené výjimky
► V některých situacích je vhodné v rámci ošetření výjimky vyvolat
jinou výjimku, a přitom umožnit zjistit,
která výjimka byla prvotním hybatelem celé akce
► Řada výjimek má mezi svými konstruktory i takové,
které akceptují jako poslední parametr
odkaz na výjimku, jež byla příčinou vyvolání dané výjimky
► Chce-li se program zeptat výjimky na výjimku, která ji způsobila,
použije metodu
public Throwable getCause()
► Ve zprávě o vyvolání výjimky jsou místa, kde byla jedna výjimka
nahrazena jinou, označována textem caused by:
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
22
Ukázka výpisu při zřetězení výjimek
HighLevelException: MidLevelException: LowLevelException
at Junk.a(Junk.java:13)
at Junk.main(Junk.java:4)
Caused by: MidLevelException: LowLevelException
at Junk.c(Junk.java:23)
at Junk.b(Junk.java:17)
at Junk.a(Junk.java:11)
... 1 more
Caused by: LowLevelException
at Junk.e(Junk.java:30)
at Junk.d(Junk.java:27)
at Junk.c(Junk.java:21)
... 3 more
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
23
Převod kontrolovaných na nekontrolované
► Ošetřování kontrolovaných výjimek obtěžuje
► Víme-li, že k dané výjimce nejspíš nedojde
a ošetřujeme-li ji pouze proto, že na tom překladač trvá,
můžeme pro případ, že by k výjimce přece jenom došlo
zaměnit kontrolovanou výjimku za nekontrolovanou
public void prevod( String s ) {
try {
prověř( s );
} catch( Exception ex ) {
throw new RuntimeException( " Neprověřeno! ", ex );
}
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
24
Vaše jistota na trhu IT
Definice vlastních výjimek
►Hierarchie výjimek
►Pořadí výjimek v blocích catch
►Metody generující výjimky
►Metody třídy Throwable
►Vlastní výjimky
►Zásady správného používání výjimek
Definice vlastních výjimek
► Výjimky jsou zcela běžné třídy;
považujeme-li to proto za vhodné, můžeme definovat i vlastní
► Před definicí nové výjimky bychom si měli ujasnit,
bude-li kontrolovaná či nekontrolovaná;
podle toho definujeme jejího předka
► Název výjimek končí dle konvencí slovem Exception
před nímž je naznačena podstata dané výjimky
● IllegalArgumetnException
● NoSuchMethodException
● BadStringOperationException
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
26
Příklad vlastní kontrolované výjimky
public class VelkýPrůšvihException
extends Exception
{
public VelkýPrůšvihException() {};
public VelkýPrůšvihException( String zpráva ) {
super( zpráva );
}
public VelkýPrůšvihException(String zpráva,
Throwable původce ) {
super( zpráva, původce );
}
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
27
Test správného vyhození výjimky
► Na vytvářených programech je třeba otestovat i to,
že v definovaných situacích vyhodí požadovanou výjimku
public void testVyhozeníVýjimky()
{
try {
metodaKteráMáVyhoditVýjimku();
} catch ( VelkýPrůšvihException vpe ) {
return;
}
fail( "Nebyla vyhozena výjimka VelkýPrůšvihException" );
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
28
Zásady správného používání výjimek
1/2
Neignorujte
výjimky
try {
//Nějaký kód
}
catch(Exception e){}
► Výjimky, o nichž víte, že nemohou nastat,
převeďte na nekontrolované pro případ,
že by v budoucích verzích programu nastat mohly
► Při ošetřování výjimek, které nastat mohou,
ale nemají vliv na chod programu,
vložte do těla ošetření alespoň vysvětlující komentář
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
29
Zásady správného používání výjimek
2/2
► Používejte výjimky pouze k ošetření výjimečných stavů
► Kontrolované výjimky používejte u stavů, z nichž se lze zotavit,
jinak použijte výjimky nekontrolované
► Vyhýbejte se zbytečnému používání kontrolovaných výjimek
● Programátory ošetřování kontrolovaných výjimek obtěžuje
a mají pak tendenci je ošetřovat prázdným blokem catch
► Dávejte přednost standardním výjimkám,
vyvolávejte výjimky odpovídající dané abstrakci
● Programátoři by měli z názvu výjimky poznat, co se stalo
● Standardní výjimky mají všeobecně známý význam
► Snažte se o atomičnost selhání; i po vyhození výjimky
by měl být objekt v dobře definovaném stavu
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
30
Zásady správného používání výjimek
3/2
► Doplňujte výjimky zprávami,
výjimka by sama měla poskytnout dostatek informací
a neměla by programátora nutit k podrobnější analýze programu
► Dokumentujte vyvolávané výjimky v dokumentačních
komentářích pomocí značky @throws
► Nedělejte bloky try zbytečně velké,
kód uvnitř těchto bloků se neoptimalizuje
► Umíte-li výjimku v metodě ošetřit, udělejte to
► Detekuje-li se chyba v jedné metodě a má se ošetřit v jiné
(stejné či jiné instance), použijte výjimku.
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
31
Nejčastěji používané výjimky
1/2
► IllegalArgumentException
Byla zadána nepovolená hodnota parametru
● Např. chci nastavit zápornou velikost grafického tvaru
► IllegalStateException
V daném stavu objektu nelze metodu provést
● Např. otevřu soubor, přečtu pár vět, zavřu soubor a chci znovu přečíst větu
► NullPointerException
Byla vyvolána metoda instance, na níž ukazuje prázdný odkaz,
nebo byl předán nepovolený prázdný odkaz v parametru
► ArrayIndexOutOfBoundException
Byly zadány špatné meze pole, buď záporné nebo moc velké
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
32
Nejčastěji používané výjimky
2/2
► ConcurrentModificationException
V průběhu iterace byla změněna struktura kontejneru
● Např. byl do kontejneru přidán prvek
► NumberFormatException
Je požadován špatný převod řetězce na číslo či naopak
● Chci-li např. převést na číslo řetězec, který není číslem
● Častá chyba v metodách String.format či PrintStream.printf
► ClassCastException
Požadované přetypování není možné
► UnsupportedOperationException
Požadovaná operace není podporována
(např. chci přidat prvek do neměnného kontejneru)
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
33
Vaše jistota na trhu IT
Děkuji za pozornost
►Rudolf Pecinovský
http://vyuka.pecinovsky.cz/vse
mail: [email protected]
ICQ: 158 156 600
Slide 27
Vaše jistota na trhu IT
Výjimky
Rudolf Pecinovský
[email protected]
Vaše jistota na trhu IT
Obsah s odkazy
►Výjimky
►Výjimky kontrolované a nekontrolované
►Definice vlastních výjimek
Vaše jistota na trhu IT
Výjimky
►Výjimečné situace v programech
►Ošetření nestandardních situací v Javě
►Zpráva o výjimce
►Klíčová slova
►Činnost
►Vyvolání
Výjimečné situace v programech
► V každém programu je alespoň jedna chyba –
program na ni musí být připraven
► Starší programy
● Program vypsal chybové hlášení a ukončil činnost;
● V některých situacích (válcovací stolice, autopilot, …) nepřijatelné
● Funkce vrátí hodnotu signalizující chybu
● Programátor musí neustále testovat, co funkce vrací
● Knihovna měla pro tyto účely vyhrazenu speciální proměnnou,
do níž se v případě chyby zapsal její kód; nahlédnutím do proměnné
program zjistil kód poslední chyby
● Programátor musí neustále testovat, jaká je v proměnné hodnota
► Některé jazyky (Cobol, PL/1, …) proto přišly s koncepcí
ošetření nestandardních situací
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
4
Ošetření nestandardních situací v Javě
► Výjimečná událost =
problém, který brání dalšímu vykonávání části kódu
► Událost je výjimečná v tom, že na rozdíl od běžných problémů
nemá program k vyřešení situace dost informaci
► Program může při výskytu výjimečné události vyvolat výjimku
► Výjimka (exception)
objekt určený k přenosu informací o nastalém problému
z místa jeho vzniku do místa, kde bude problém řešen
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
5
Postup při vyvolání výjimky
1. Vytvoří se výjimka = objekt typu Throwable
(prakticky vždy instance některého z potomků)
2. Vytvořená výjimka se vyhodí =
přeruší se běh programu v místě, kde výjimka vznikla,
a začne se hledat místo, kde bude daná výjimka ošetřena
3. Ošetření výjimky (handler) by mělo uvést program do stavu,
v němž může jeho vykonávání pokračovat
► Výjimka „probublává“ programem z místa vyhození stále výše
a nenarazí-li cestou nikde na své ošetření,
zachytí ji virtuální stroj, který na standardní chybový výstup
vypíše zprávu o vzniku výjimky
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
6
Systémová zpráva o vzniku výjimky
Zpráva o vzniku výjimky spolu s názvem vlákna,
v němž k výjimce došlo (zde AWT-EventQueue-0)
Popis druhu výjimky (aritmetická výjimka dělení nulou)
Informace o místě, odkud byla volána metoda,
která vyvolala metodu, v níž došlo k vyhození výjimky
Informace o místě, odkud byla volána metoda,
v níž došlo k vyhození výjimky
Úplný název třídy včetně balíčku
Copyright © 2006, Rudolf Pecinovský
Název metody
VŠE – 05
Název souboru se
zdrojovým kódem
Číslo řádku zdrojáku,
kde došlo k výjimce
7
Klíčová slova související s výjimkami
► try (zkus)
Označuje blok kódu, v němž může dojít k výjimce
► throw (hoď)
Příkaz k vyhození výjimky;
musí být následován odkazem na existující instanci
► catch (chyť)
Blok ošetřující výjimku, která je zadána jako parametr
► finally (na konec)
Blok s povinnými závěrečnými akcemi nezávisejícími
na případném vzniku výjimky
► throws (hází)
Uvození seznamu výjimek vyhazovaných danou metodou
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
8
Vyvolání a ošetření výjimky v kódu
try {
//Kód, který může vyvolat výjimky
}
catch( Typ1 id1 ) {
//Ošetření výjimek typu Typ1
}
...
catch( TypN idN ) {
//ošetření výjimek typu TypN
}
finally {
//Kód, který se na závěr VŽDY provede
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
9
Náznak činnosti – řádný průběh
nedojde k vyvolání výjimky
= nedojde k chybě
try {
příkaz1();
příkaz2();
příkaz3();
}
catch ( xxxException e ) {
příkazProOšetřeníChyby();
}
Bloky catch
catch (…..
se přeskočí
finally {
ukončovacíPříkazy();
}
dalšíPříkaz();
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
12
Náznak činnosti – ošetřený výjimka
try {
příkaz1(); Při provádění metody příkaz2
dojde k ošetřené chybě
příkaz2();
příkaz3();
Byla vyhozena výjimka
tohoto typu nebo typu
}
některého z potomků
catch ( xxxException e ) {
příkazProOšetřeníChyby();
}
Ostatní bloky catch
catch (…..
se přeskočí
finally {
ukončovacíPříkazy();
}
dalšíPříkaz();
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
13
Náznak činnosti – neošetřená výjimka
Při provádění metody příkaz2
dojde k NEošetřené chybě
try {
příkaz1();
příkaz2();
příkaz3();
}
catch ( xxxException e ) {
příkazProOšetřeníChyby();
}
Ošetření nebylo nalezeno =>
catch (…..
provede se blok finally
a opouští se metoda
finally {
ukončovacíPříkazy();
}
dalšíPříkaz();
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
14
Vyvolání výjimky
public class Xyz implements Comparable
{
public bolean compareTo( Object o )
{
if( !(o instanceOf Xyz) )
throw new ClassCastException (
"\nPokus o porovnání s neporovnatelnou"
+ " instancí " + o );
//Zjištění, kdo je větší
return vysledek;
}
}
► Instanci nemusíme vytvářet až v příkazu throw,
můžeme ji vytvořit kdykoliv před tím a pak mu ji jen předat
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
15
Vaše jistota na trhu IT
Výjimky kontrolované a
nekontrolované
►Hierarchie výjimek
►Pořadí výjimek v blocích catch
►Metody generující výjimky
►Metody třídy Throwable
►Zřetězené výjimky
►Převod kontrolovaných na nekontrolované
Charakteristika
► Výjimky, které jsou potomky třídy RuntimeException
nebo Error označujeme jako nekontrolované (unchecked),
protože překladač nekontroluje, zda je na ně program připraven
► Ostatní výjimky označujeme jako kontrolované (checked),
protože překladač kontroluje dodržení pravidel:
● Každá metoda, která může vyhodit kontrolovanou výjimku,
se musí k této skutečnosti veřejně přihlásit
● Každé použití metody, která může vyhodit kontrolovanou výjimku,
musí být buď uzavřeno v bloku try…catch,
nebo se volající metoda musí přihlásit k tomu,
že může také vyhodit danou kontrolovanou výjimku
► Nekontrolované výjimky ohlašují chyby v programu,
kontrolované výjimky očekávatelné situace,
na jejichž výskyt má být program připraven
a měl by na ně umět reagovat
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
17
Hierarchie výjimek
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
18
Pořadí výjimek v blocích catch
► Třída NumberFormatException
je potomkem třídy RuntimeException
try {
Syntaktická chyba,
......
na druhý blok catch nikdy nedojde
}
catch (RuntimeException e) {
.........
}
Obrácené pořadí bloků catch
catch (NumberFormatException e){
vše vyřeší
........
try {
}
......
}
catch (NumberFormatException e) {
.........
}
catch (RuntimeException e){
........
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
19
Metody generující výjimky
► Java vyžaduje, aby programy, které používají metody
schopné vyvolat kontrolované výjimky,
byly o této schopnosti používaných metod informovány =>
pak vědí, které výjimku musí umět zachytit a ošetřit
► Všechny kontrolované výjimky, které může metoda vyhodit,
musí deklarovat v hlavičce za klíčovým slovem throws
► Deklarace vyhazování nekontrolovaných výjimek není povinná
public void metoda()
throws KontrolovanáVýjimka1,
KontrolovanáVýjimka2
{
// Tělo metody
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
20
Metody třídy Throwable
► String getMessage()
Vrátí zprávu popisující danou výjimku
► String toString()
Vrátí název třídy výjimky následovaný případnou zprávou
► void printStackTrace()
Vytiskne toString() následovaný sadou informací o volající
posloupnosti, která vedla k vzniku výjimky
► Throwable fillInStackTrace()
Připraví nové informace o volací posloupnosti
vedoucí k místu zavolání této metody
► StackTraceElement[] getStackTrace()
Vrátí uchované informace o volací posloupnosti dané výjimky
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
21
Zřetězené výjimky
► V některých situacích je vhodné v rámci ošetření výjimky vyvolat
jinou výjimku, a přitom umožnit zjistit,
která výjimka byla prvotním hybatelem celé akce
► Řada výjimek má mezi svými konstruktory i takové,
které akceptují jako poslední parametr
odkaz na výjimku, jež byla příčinou vyvolání dané výjimky
► Chce-li se program zeptat výjimky na výjimku, která ji způsobila,
použije metodu
public Throwable getCause()
► Ve zprávě o vyvolání výjimky jsou místa, kde byla jedna výjimka
nahrazena jinou, označována textem caused by:
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
22
Ukázka výpisu při zřetězení výjimek
HighLevelException: MidLevelException: LowLevelException
at Junk.a(Junk.java:13)
at Junk.main(Junk.java:4)
Caused by: MidLevelException: LowLevelException
at Junk.c(Junk.java:23)
at Junk.b(Junk.java:17)
at Junk.a(Junk.java:11)
... 1 more
Caused by: LowLevelException
at Junk.e(Junk.java:30)
at Junk.d(Junk.java:27)
at Junk.c(Junk.java:21)
... 3 more
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
23
Převod kontrolovaných na nekontrolované
► Ošetřování kontrolovaných výjimek obtěžuje
► Víme-li, že k dané výjimce nejspíš nedojde
a ošetřujeme-li ji pouze proto, že na tom překladač trvá,
můžeme pro případ, že by k výjimce přece jenom došlo
zaměnit kontrolovanou výjimku za nekontrolovanou
public void prevod( String s ) {
try {
prověř( s );
} catch( Exception ex ) {
throw new RuntimeException( " Neprověřeno! ", ex );
}
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
24
Vaše jistota na trhu IT
Definice vlastních výjimek
►Hierarchie výjimek
►Pořadí výjimek v blocích catch
►Metody generující výjimky
►Metody třídy Throwable
►Vlastní výjimky
►Zásady správného používání výjimek
Definice vlastních výjimek
► Výjimky jsou zcela běžné třídy;
považujeme-li to proto za vhodné, můžeme definovat i vlastní
► Před definicí nové výjimky bychom si měli ujasnit,
bude-li kontrolovaná či nekontrolovaná;
podle toho definujeme jejího předka
► Název výjimek končí dle konvencí slovem Exception
před nímž je naznačena podstata dané výjimky
● IllegalArgumetnException
● NoSuchMethodException
● BadStringOperationException
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
26
Příklad vlastní kontrolované výjimky
public class VelkýPrůšvihException
extends Exception
{
public VelkýPrůšvihException() {};
public VelkýPrůšvihException( String zpráva ) {
super( zpráva );
}
public VelkýPrůšvihException(String zpráva,
Throwable původce ) {
super( zpráva, původce );
}
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
27
Test správného vyhození výjimky
► Na vytvářených programech je třeba otestovat i to,
že v definovaných situacích vyhodí požadovanou výjimku
public void testVyhozeníVýjimky()
{
try {
metodaKteráMáVyhoditVýjimku();
} catch ( VelkýPrůšvihException vpe ) {
return;
}
fail( "Nebyla vyhozena výjimka VelkýPrůšvihException" );
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
28
Zásady správného používání výjimek
1/2
Neignorujte
výjimky
try {
//Nějaký kód
}
catch(Exception e){}
► Výjimky, o nichž víte, že nemohou nastat,
převeďte na nekontrolované pro případ,
že by v budoucích verzích programu nastat mohly
► Při ošetřování výjimek, které nastat mohou,
ale nemají vliv na chod programu,
vložte do těla ošetření alespoň vysvětlující komentář
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
29
Zásady správného používání výjimek
2/2
► Používejte výjimky pouze k ošetření výjimečných stavů
► Kontrolované výjimky používejte u stavů, z nichž se lze zotavit,
jinak použijte výjimky nekontrolované
► Vyhýbejte se zbytečnému používání kontrolovaných výjimek
● Programátory ošetřování kontrolovaných výjimek obtěžuje
a mají pak tendenci je ošetřovat prázdným blokem catch
► Dávejte přednost standardním výjimkám,
vyvolávejte výjimky odpovídající dané abstrakci
● Programátoři by měli z názvu výjimky poznat, co se stalo
● Standardní výjimky mají všeobecně známý význam
► Snažte se o atomičnost selhání; i po vyhození výjimky
by měl být objekt v dobře definovaném stavu
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
30
Zásady správného používání výjimek
3/2
► Doplňujte výjimky zprávami,
výjimka by sama měla poskytnout dostatek informací
a neměla by programátora nutit k podrobnější analýze programu
► Dokumentujte vyvolávané výjimky v dokumentačních
komentářích pomocí značky @throws
► Nedělejte bloky try zbytečně velké,
kód uvnitř těchto bloků se neoptimalizuje
► Umíte-li výjimku v metodě ošetřit, udělejte to
► Detekuje-li se chyba v jedné metodě a má se ošetřit v jiné
(stejné či jiné instance), použijte výjimku.
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
31
Nejčastěji používané výjimky
1/2
► IllegalArgumentException
Byla zadána nepovolená hodnota parametru
● Např. chci nastavit zápornou velikost grafického tvaru
► IllegalStateException
V daném stavu objektu nelze metodu provést
● Např. otevřu soubor, přečtu pár vět, zavřu soubor a chci znovu přečíst větu
► NullPointerException
Byla vyvolána metoda instance, na níž ukazuje prázdný odkaz,
nebo byl předán nepovolený prázdný odkaz v parametru
► ArrayIndexOutOfBoundException
Byly zadány špatné meze pole, buď záporné nebo moc velké
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
32
Nejčastěji používané výjimky
2/2
► ConcurrentModificationException
V průběhu iterace byla změněna struktura kontejneru
● Např. byl do kontejneru přidán prvek
► NumberFormatException
Je požadován špatný převod řetězce na číslo či naopak
● Chci-li např. převést na číslo řetězec, který není číslem
● Častá chyba v metodách String.format či PrintStream.printf
► ClassCastException
Požadované přetypování není možné
► UnsupportedOperationException
Požadovaná operace není podporována
(např. chci přidat prvek do neměnného kontejneru)
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
33
Vaše jistota na trhu IT
Děkuji za pozornost
►Rudolf Pecinovský
http://vyuka.pecinovsky.cz/vse
mail: [email protected]
ICQ: 158 156 600
Slide 28
Vaše jistota na trhu IT
Výjimky
Rudolf Pecinovský
[email protected]
Vaše jistota na trhu IT
Obsah s odkazy
►Výjimky
►Výjimky kontrolované a nekontrolované
►Definice vlastních výjimek
Vaše jistota na trhu IT
Výjimky
►Výjimečné situace v programech
►Ošetření nestandardních situací v Javě
►Zpráva o výjimce
►Klíčová slova
►Činnost
►Vyvolání
Výjimečné situace v programech
► V každém programu je alespoň jedna chyba –
program na ni musí být připraven
► Starší programy
● Program vypsal chybové hlášení a ukončil činnost;
● V některých situacích (válcovací stolice, autopilot, …) nepřijatelné
● Funkce vrátí hodnotu signalizující chybu
● Programátor musí neustále testovat, co funkce vrací
● Knihovna měla pro tyto účely vyhrazenu speciální proměnnou,
do níž se v případě chyby zapsal její kód; nahlédnutím do proměnné
program zjistil kód poslední chyby
● Programátor musí neustále testovat, jaká je v proměnné hodnota
► Některé jazyky (Cobol, PL/1, …) proto přišly s koncepcí
ošetření nestandardních situací
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
4
Ošetření nestandardních situací v Javě
► Výjimečná událost =
problém, který brání dalšímu vykonávání části kódu
► Událost je výjimečná v tom, že na rozdíl od běžných problémů
nemá program k vyřešení situace dost informaci
► Program může při výskytu výjimečné události vyvolat výjimku
► Výjimka (exception)
objekt určený k přenosu informací o nastalém problému
z místa jeho vzniku do místa, kde bude problém řešen
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
5
Postup při vyvolání výjimky
1. Vytvoří se výjimka = objekt typu Throwable
(prakticky vždy instance některého z potomků)
2. Vytvořená výjimka se vyhodí =
přeruší se běh programu v místě, kde výjimka vznikla,
a začne se hledat místo, kde bude daná výjimka ošetřena
3. Ošetření výjimky (handler) by mělo uvést program do stavu,
v němž může jeho vykonávání pokračovat
► Výjimka „probublává“ programem z místa vyhození stále výše
a nenarazí-li cestou nikde na své ošetření,
zachytí ji virtuální stroj, který na standardní chybový výstup
vypíše zprávu o vzniku výjimky
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
6
Systémová zpráva o vzniku výjimky
Zpráva o vzniku výjimky spolu s názvem vlákna,
v němž k výjimce došlo (zde AWT-EventQueue-0)
Popis druhu výjimky (aritmetická výjimka dělení nulou)
Informace o místě, odkud byla volána metoda,
která vyvolala metodu, v níž došlo k vyhození výjimky
Informace o místě, odkud byla volána metoda,
v níž došlo k vyhození výjimky
Úplný název třídy včetně balíčku
Copyright © 2006, Rudolf Pecinovský
Název metody
VŠE – 05
Název souboru se
zdrojovým kódem
Číslo řádku zdrojáku,
kde došlo k výjimce
7
Klíčová slova související s výjimkami
► try (zkus)
Označuje blok kódu, v němž může dojít k výjimce
► throw (hoď)
Příkaz k vyhození výjimky;
musí být následován odkazem na existující instanci
► catch (chyť)
Blok ošetřující výjimku, která je zadána jako parametr
► finally (na konec)
Blok s povinnými závěrečnými akcemi nezávisejícími
na případném vzniku výjimky
► throws (hází)
Uvození seznamu výjimek vyhazovaných danou metodou
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
8
Vyvolání a ošetření výjimky v kódu
try {
//Kód, který může vyvolat výjimky
}
catch( Typ1 id1 ) {
//Ošetření výjimek typu Typ1
}
...
catch( TypN idN ) {
//ošetření výjimek typu TypN
}
finally {
//Kód, který se na závěr VŽDY provede
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
9
Náznak činnosti – řádný průběh
nedojde k vyvolání výjimky
= nedojde k chybě
try {
příkaz1();
příkaz2();
příkaz3();
}
catch ( xxxException e ) {
příkazProOšetřeníChyby();
}
Bloky catch
catch (…..
se přeskočí
finally {
ukončovacíPříkazy();
}
dalšíPříkaz();
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
12
Náznak činnosti – ošetřený výjimka
try {
příkaz1(); Při provádění metody příkaz2
dojde k ošetřené chybě
příkaz2();
příkaz3();
Byla vyhozena výjimka
tohoto typu nebo typu
}
některého z potomků
catch ( xxxException e ) {
příkazProOšetřeníChyby();
}
Ostatní bloky catch
catch (…..
se přeskočí
finally {
ukončovacíPříkazy();
}
dalšíPříkaz();
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
13
Náznak činnosti – neošetřená výjimka
Při provádění metody příkaz2
dojde k NEošetřené chybě
try {
příkaz1();
příkaz2();
příkaz3();
}
catch ( xxxException e ) {
příkazProOšetřeníChyby();
}
Ošetření nebylo nalezeno =>
catch (…..
provede se blok finally
a opouští se metoda
finally {
ukončovacíPříkazy();
}
dalšíPříkaz();
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
14
Vyvolání výjimky
public class Xyz implements Comparable
{
public bolean compareTo( Object o )
{
if( !(o instanceOf Xyz) )
throw new ClassCastException (
"\nPokus o porovnání s neporovnatelnou"
+ " instancí " + o );
//Zjištění, kdo je větší
return vysledek;
}
}
► Instanci nemusíme vytvářet až v příkazu throw,
můžeme ji vytvořit kdykoliv před tím a pak mu ji jen předat
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
15
Vaše jistota na trhu IT
Výjimky kontrolované a
nekontrolované
►Hierarchie výjimek
►Pořadí výjimek v blocích catch
►Metody generující výjimky
►Metody třídy Throwable
►Zřetězené výjimky
►Převod kontrolovaných na nekontrolované
Charakteristika
► Výjimky, které jsou potomky třídy RuntimeException
nebo Error označujeme jako nekontrolované (unchecked),
protože překladač nekontroluje, zda je na ně program připraven
► Ostatní výjimky označujeme jako kontrolované (checked),
protože překladač kontroluje dodržení pravidel:
● Každá metoda, která může vyhodit kontrolovanou výjimku,
se musí k této skutečnosti veřejně přihlásit
● Každé použití metody, která může vyhodit kontrolovanou výjimku,
musí být buď uzavřeno v bloku try…catch,
nebo se volající metoda musí přihlásit k tomu,
že může také vyhodit danou kontrolovanou výjimku
► Nekontrolované výjimky ohlašují chyby v programu,
kontrolované výjimky očekávatelné situace,
na jejichž výskyt má být program připraven
a měl by na ně umět reagovat
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
17
Hierarchie výjimek
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
18
Pořadí výjimek v blocích catch
► Třída NumberFormatException
je potomkem třídy RuntimeException
try {
Syntaktická chyba,
......
na druhý blok catch nikdy nedojde
}
catch (RuntimeException e) {
.........
}
Obrácené pořadí bloků catch
catch (NumberFormatException e){
vše vyřeší
........
try {
}
......
}
catch (NumberFormatException e) {
.........
}
catch (RuntimeException e){
........
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
19
Metody generující výjimky
► Java vyžaduje, aby programy, které používají metody
schopné vyvolat kontrolované výjimky,
byly o této schopnosti používaných metod informovány =>
pak vědí, které výjimku musí umět zachytit a ošetřit
► Všechny kontrolované výjimky, které může metoda vyhodit,
musí deklarovat v hlavičce za klíčovým slovem throws
► Deklarace vyhazování nekontrolovaných výjimek není povinná
public void metoda()
throws KontrolovanáVýjimka1,
KontrolovanáVýjimka2
{
// Tělo metody
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
20
Metody třídy Throwable
► String getMessage()
Vrátí zprávu popisující danou výjimku
► String toString()
Vrátí název třídy výjimky následovaný případnou zprávou
► void printStackTrace()
Vytiskne toString() následovaný sadou informací o volající
posloupnosti, která vedla k vzniku výjimky
► Throwable fillInStackTrace()
Připraví nové informace o volací posloupnosti
vedoucí k místu zavolání této metody
► StackTraceElement[] getStackTrace()
Vrátí uchované informace o volací posloupnosti dané výjimky
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
21
Zřetězené výjimky
► V některých situacích je vhodné v rámci ošetření výjimky vyvolat
jinou výjimku, a přitom umožnit zjistit,
která výjimka byla prvotním hybatelem celé akce
► Řada výjimek má mezi svými konstruktory i takové,
které akceptují jako poslední parametr
odkaz na výjimku, jež byla příčinou vyvolání dané výjimky
► Chce-li se program zeptat výjimky na výjimku, která ji způsobila,
použije metodu
public Throwable getCause()
► Ve zprávě o vyvolání výjimky jsou místa, kde byla jedna výjimka
nahrazena jinou, označována textem caused by:
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
22
Ukázka výpisu při zřetězení výjimek
HighLevelException: MidLevelException: LowLevelException
at Junk.a(Junk.java:13)
at Junk.main(Junk.java:4)
Caused by: MidLevelException: LowLevelException
at Junk.c(Junk.java:23)
at Junk.b(Junk.java:17)
at Junk.a(Junk.java:11)
... 1 more
Caused by: LowLevelException
at Junk.e(Junk.java:30)
at Junk.d(Junk.java:27)
at Junk.c(Junk.java:21)
... 3 more
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
23
Převod kontrolovaných na nekontrolované
► Ošetřování kontrolovaných výjimek obtěžuje
► Víme-li, že k dané výjimce nejspíš nedojde
a ošetřujeme-li ji pouze proto, že na tom překladač trvá,
můžeme pro případ, že by k výjimce přece jenom došlo
zaměnit kontrolovanou výjimku za nekontrolovanou
public void prevod( String s ) {
try {
prověř( s );
} catch( Exception ex ) {
throw new RuntimeException( " Neprověřeno! ", ex );
}
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
24
Vaše jistota na trhu IT
Definice vlastních výjimek
►Hierarchie výjimek
►Pořadí výjimek v blocích catch
►Metody generující výjimky
►Metody třídy Throwable
►Vlastní výjimky
►Zásady správného používání výjimek
Definice vlastních výjimek
► Výjimky jsou zcela běžné třídy;
považujeme-li to proto za vhodné, můžeme definovat i vlastní
► Před definicí nové výjimky bychom si měli ujasnit,
bude-li kontrolovaná či nekontrolovaná;
podle toho definujeme jejího předka
► Název výjimek končí dle konvencí slovem Exception
před nímž je naznačena podstata dané výjimky
● IllegalArgumetnException
● NoSuchMethodException
● BadStringOperationException
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
26
Příklad vlastní kontrolované výjimky
public class VelkýPrůšvihException
extends Exception
{
public VelkýPrůšvihException() {};
public VelkýPrůšvihException( String zpráva ) {
super( zpráva );
}
public VelkýPrůšvihException(String zpráva,
Throwable původce ) {
super( zpráva, původce );
}
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
27
Test správného vyhození výjimky
► Na vytvářených programech je třeba otestovat i to,
že v definovaných situacích vyhodí požadovanou výjimku
public void testVyhozeníVýjimky()
{
try {
metodaKteráMáVyhoditVýjimku();
} catch ( VelkýPrůšvihException vpe ) {
return;
}
fail( "Nebyla vyhozena výjimka VelkýPrůšvihException" );
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
28
Zásady správného používání výjimek
1/2
Neignorujte
výjimky
try {
//Nějaký kód
}
catch(Exception e){}
► Výjimky, o nichž víte, že nemohou nastat,
převeďte na nekontrolované pro případ,
že by v budoucích verzích programu nastat mohly
► Při ošetřování výjimek, které nastat mohou,
ale nemají vliv na chod programu,
vložte do těla ošetření alespoň vysvětlující komentář
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
29
Zásady správného používání výjimek
2/2
► Používejte výjimky pouze k ošetření výjimečných stavů
► Kontrolované výjimky používejte u stavů, z nichž se lze zotavit,
jinak použijte výjimky nekontrolované
► Vyhýbejte se zbytečnému používání kontrolovaných výjimek
● Programátory ošetřování kontrolovaných výjimek obtěžuje
a mají pak tendenci je ošetřovat prázdným blokem catch
► Dávejte přednost standardním výjimkám,
vyvolávejte výjimky odpovídající dané abstrakci
● Programátoři by měli z názvu výjimky poznat, co se stalo
● Standardní výjimky mají všeobecně známý význam
► Snažte se o atomičnost selhání; i po vyhození výjimky
by měl být objekt v dobře definovaném stavu
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
30
Zásady správného používání výjimek
3/2
► Doplňujte výjimky zprávami,
výjimka by sama měla poskytnout dostatek informací
a neměla by programátora nutit k podrobnější analýze programu
► Dokumentujte vyvolávané výjimky v dokumentačních
komentářích pomocí značky @throws
► Nedělejte bloky try zbytečně velké,
kód uvnitř těchto bloků se neoptimalizuje
► Umíte-li výjimku v metodě ošetřit, udělejte to
► Detekuje-li se chyba v jedné metodě a má se ošetřit v jiné
(stejné či jiné instance), použijte výjimku.
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
31
Nejčastěji používané výjimky
1/2
► IllegalArgumentException
Byla zadána nepovolená hodnota parametru
● Např. chci nastavit zápornou velikost grafického tvaru
► IllegalStateException
V daném stavu objektu nelze metodu provést
● Např. otevřu soubor, přečtu pár vět, zavřu soubor a chci znovu přečíst větu
► NullPointerException
Byla vyvolána metoda instance, na níž ukazuje prázdný odkaz,
nebo byl předán nepovolený prázdný odkaz v parametru
► ArrayIndexOutOfBoundException
Byly zadány špatné meze pole, buď záporné nebo moc velké
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
32
Nejčastěji používané výjimky
2/2
► ConcurrentModificationException
V průběhu iterace byla změněna struktura kontejneru
● Např. byl do kontejneru přidán prvek
► NumberFormatException
Je požadován špatný převod řetězce na číslo či naopak
● Chci-li např. převést na číslo řetězec, který není číslem
● Častá chyba v metodách String.format či PrintStream.printf
► ClassCastException
Požadované přetypování není možné
► UnsupportedOperationException
Požadovaná operace není podporována
(např. chci přidat prvek do neměnného kontejneru)
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
33
Vaše jistota na trhu IT
Děkuji za pozornost
►Rudolf Pecinovský
http://vyuka.pecinovsky.cz/vse
mail: [email protected]
ICQ: 158 156 600
Slide 29
Vaše jistota na trhu IT
Výjimky
Rudolf Pecinovský
[email protected]
Vaše jistota na trhu IT
Obsah s odkazy
►Výjimky
►Výjimky kontrolované a nekontrolované
►Definice vlastních výjimek
Vaše jistota na trhu IT
Výjimky
►Výjimečné situace v programech
►Ošetření nestandardních situací v Javě
►Zpráva o výjimce
►Klíčová slova
►Činnost
►Vyvolání
Výjimečné situace v programech
► V každém programu je alespoň jedna chyba –
program na ni musí být připraven
► Starší programy
● Program vypsal chybové hlášení a ukončil činnost;
● V některých situacích (válcovací stolice, autopilot, …) nepřijatelné
● Funkce vrátí hodnotu signalizující chybu
● Programátor musí neustále testovat, co funkce vrací
● Knihovna měla pro tyto účely vyhrazenu speciální proměnnou,
do níž se v případě chyby zapsal její kód; nahlédnutím do proměnné
program zjistil kód poslední chyby
● Programátor musí neustále testovat, jaká je v proměnné hodnota
► Některé jazyky (Cobol, PL/1, …) proto přišly s koncepcí
ošetření nestandardních situací
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
4
Ošetření nestandardních situací v Javě
► Výjimečná událost =
problém, který brání dalšímu vykonávání části kódu
► Událost je výjimečná v tom, že na rozdíl od běžných problémů
nemá program k vyřešení situace dost informaci
► Program může při výskytu výjimečné události vyvolat výjimku
► Výjimka (exception)
objekt určený k přenosu informací o nastalém problému
z místa jeho vzniku do místa, kde bude problém řešen
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
5
Postup při vyvolání výjimky
1. Vytvoří se výjimka = objekt typu Throwable
(prakticky vždy instance některého z potomků)
2. Vytvořená výjimka se vyhodí =
přeruší se běh programu v místě, kde výjimka vznikla,
a začne se hledat místo, kde bude daná výjimka ošetřena
3. Ošetření výjimky (handler) by mělo uvést program do stavu,
v němž může jeho vykonávání pokračovat
► Výjimka „probublává“ programem z místa vyhození stále výše
a nenarazí-li cestou nikde na své ošetření,
zachytí ji virtuální stroj, který na standardní chybový výstup
vypíše zprávu o vzniku výjimky
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
6
Systémová zpráva o vzniku výjimky
Zpráva o vzniku výjimky spolu s názvem vlákna,
v němž k výjimce došlo (zde AWT-EventQueue-0)
Popis druhu výjimky (aritmetická výjimka dělení nulou)
Informace o místě, odkud byla volána metoda,
která vyvolala metodu, v níž došlo k vyhození výjimky
Informace o místě, odkud byla volána metoda,
v níž došlo k vyhození výjimky
Úplný název třídy včetně balíčku
Copyright © 2006, Rudolf Pecinovský
Název metody
VŠE – 05
Název souboru se
zdrojovým kódem
Číslo řádku zdrojáku,
kde došlo k výjimce
7
Klíčová slova související s výjimkami
► try (zkus)
Označuje blok kódu, v němž může dojít k výjimce
► throw (hoď)
Příkaz k vyhození výjimky;
musí být následován odkazem na existující instanci
► catch (chyť)
Blok ošetřující výjimku, která je zadána jako parametr
► finally (na konec)
Blok s povinnými závěrečnými akcemi nezávisejícími
na případném vzniku výjimky
► throws (hází)
Uvození seznamu výjimek vyhazovaných danou metodou
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
8
Vyvolání a ošetření výjimky v kódu
try {
//Kód, který může vyvolat výjimky
}
catch( Typ1 id1 ) {
//Ošetření výjimek typu Typ1
}
...
catch( TypN idN ) {
//ošetření výjimek typu TypN
}
finally {
//Kód, který se na závěr VŽDY provede
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
9
Náznak činnosti – řádný průběh
nedojde k vyvolání výjimky
= nedojde k chybě
try {
příkaz1();
příkaz2();
příkaz3();
}
catch ( xxxException e ) {
příkazProOšetřeníChyby();
}
Bloky catch
catch (…..
se přeskočí
finally {
ukončovacíPříkazy();
}
dalšíPříkaz();
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
12
Náznak činnosti – ošetřený výjimka
try {
příkaz1(); Při provádění metody příkaz2
dojde k ošetřené chybě
příkaz2();
příkaz3();
Byla vyhozena výjimka
tohoto typu nebo typu
}
některého z potomků
catch ( xxxException e ) {
příkazProOšetřeníChyby();
}
Ostatní bloky catch
catch (…..
se přeskočí
finally {
ukončovacíPříkazy();
}
dalšíPříkaz();
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
13
Náznak činnosti – neošetřená výjimka
Při provádění metody příkaz2
dojde k NEošetřené chybě
try {
příkaz1();
příkaz2();
příkaz3();
}
catch ( xxxException e ) {
příkazProOšetřeníChyby();
}
Ošetření nebylo nalezeno =>
catch (…..
provede se blok finally
a opouští se metoda
finally {
ukončovacíPříkazy();
}
dalšíPříkaz();
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
14
Vyvolání výjimky
public class Xyz implements Comparable
{
public bolean compareTo( Object o )
{
if( !(o instanceOf Xyz) )
throw new ClassCastException (
"\nPokus o porovnání s neporovnatelnou"
+ " instancí " + o );
//Zjištění, kdo je větší
return vysledek;
}
}
► Instanci nemusíme vytvářet až v příkazu throw,
můžeme ji vytvořit kdykoliv před tím a pak mu ji jen předat
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
15
Vaše jistota na trhu IT
Výjimky kontrolované a
nekontrolované
►Hierarchie výjimek
►Pořadí výjimek v blocích catch
►Metody generující výjimky
►Metody třídy Throwable
►Zřetězené výjimky
►Převod kontrolovaných na nekontrolované
Charakteristika
► Výjimky, které jsou potomky třídy RuntimeException
nebo Error označujeme jako nekontrolované (unchecked),
protože překladač nekontroluje, zda je na ně program připraven
► Ostatní výjimky označujeme jako kontrolované (checked),
protože překladač kontroluje dodržení pravidel:
● Každá metoda, která může vyhodit kontrolovanou výjimku,
se musí k této skutečnosti veřejně přihlásit
● Každé použití metody, která může vyhodit kontrolovanou výjimku,
musí být buď uzavřeno v bloku try…catch,
nebo se volající metoda musí přihlásit k tomu,
že může také vyhodit danou kontrolovanou výjimku
► Nekontrolované výjimky ohlašují chyby v programu,
kontrolované výjimky očekávatelné situace,
na jejichž výskyt má být program připraven
a měl by na ně umět reagovat
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
17
Hierarchie výjimek
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
18
Pořadí výjimek v blocích catch
► Třída NumberFormatException
je potomkem třídy RuntimeException
try {
Syntaktická chyba,
......
na druhý blok catch nikdy nedojde
}
catch (RuntimeException e) {
.........
}
Obrácené pořadí bloků catch
catch (NumberFormatException e){
vše vyřeší
........
try {
}
......
}
catch (NumberFormatException e) {
.........
}
catch (RuntimeException e){
........
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
19
Metody generující výjimky
► Java vyžaduje, aby programy, které používají metody
schopné vyvolat kontrolované výjimky,
byly o této schopnosti používaných metod informovány =>
pak vědí, které výjimku musí umět zachytit a ošetřit
► Všechny kontrolované výjimky, které může metoda vyhodit,
musí deklarovat v hlavičce za klíčovým slovem throws
► Deklarace vyhazování nekontrolovaných výjimek není povinná
public void metoda()
throws KontrolovanáVýjimka1,
KontrolovanáVýjimka2
{
// Tělo metody
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
20
Metody třídy Throwable
► String getMessage()
Vrátí zprávu popisující danou výjimku
► String toString()
Vrátí název třídy výjimky následovaný případnou zprávou
► void printStackTrace()
Vytiskne toString() následovaný sadou informací o volající
posloupnosti, která vedla k vzniku výjimky
► Throwable fillInStackTrace()
Připraví nové informace o volací posloupnosti
vedoucí k místu zavolání této metody
► StackTraceElement[] getStackTrace()
Vrátí uchované informace o volací posloupnosti dané výjimky
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
21
Zřetězené výjimky
► V některých situacích je vhodné v rámci ošetření výjimky vyvolat
jinou výjimku, a přitom umožnit zjistit,
která výjimka byla prvotním hybatelem celé akce
► Řada výjimek má mezi svými konstruktory i takové,
které akceptují jako poslední parametr
odkaz na výjimku, jež byla příčinou vyvolání dané výjimky
► Chce-li se program zeptat výjimky na výjimku, která ji způsobila,
použije metodu
public Throwable getCause()
► Ve zprávě o vyvolání výjimky jsou místa, kde byla jedna výjimka
nahrazena jinou, označována textem caused by:
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
22
Ukázka výpisu při zřetězení výjimek
HighLevelException: MidLevelException: LowLevelException
at Junk.a(Junk.java:13)
at Junk.main(Junk.java:4)
Caused by: MidLevelException: LowLevelException
at Junk.c(Junk.java:23)
at Junk.b(Junk.java:17)
at Junk.a(Junk.java:11)
... 1 more
Caused by: LowLevelException
at Junk.e(Junk.java:30)
at Junk.d(Junk.java:27)
at Junk.c(Junk.java:21)
... 3 more
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
23
Převod kontrolovaných na nekontrolované
► Ošetřování kontrolovaných výjimek obtěžuje
► Víme-li, že k dané výjimce nejspíš nedojde
a ošetřujeme-li ji pouze proto, že na tom překladač trvá,
můžeme pro případ, že by k výjimce přece jenom došlo
zaměnit kontrolovanou výjimku za nekontrolovanou
public void prevod( String s ) {
try {
prověř( s );
} catch( Exception ex ) {
throw new RuntimeException( " Neprověřeno! ", ex );
}
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
24
Vaše jistota na trhu IT
Definice vlastních výjimek
►Hierarchie výjimek
►Pořadí výjimek v blocích catch
►Metody generující výjimky
►Metody třídy Throwable
►Vlastní výjimky
►Zásady správného používání výjimek
Definice vlastních výjimek
► Výjimky jsou zcela běžné třídy;
považujeme-li to proto za vhodné, můžeme definovat i vlastní
► Před definicí nové výjimky bychom si měli ujasnit,
bude-li kontrolovaná či nekontrolovaná;
podle toho definujeme jejího předka
► Název výjimek končí dle konvencí slovem Exception
před nímž je naznačena podstata dané výjimky
● IllegalArgumetnException
● NoSuchMethodException
● BadStringOperationException
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
26
Příklad vlastní kontrolované výjimky
public class VelkýPrůšvihException
extends Exception
{
public VelkýPrůšvihException() {};
public VelkýPrůšvihException( String zpráva ) {
super( zpráva );
}
public VelkýPrůšvihException(String zpráva,
Throwable původce ) {
super( zpráva, původce );
}
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
27
Test správného vyhození výjimky
► Na vytvářených programech je třeba otestovat i to,
že v definovaných situacích vyhodí požadovanou výjimku
public void testVyhozeníVýjimky()
{
try {
metodaKteráMáVyhoditVýjimku();
} catch ( VelkýPrůšvihException vpe ) {
return;
}
fail( "Nebyla vyhozena výjimka VelkýPrůšvihException" );
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
28
Zásady správného používání výjimek
1/2
Neignorujte
výjimky
try {
//Nějaký kód
}
catch(Exception e){}
► Výjimky, o nichž víte, že nemohou nastat,
převeďte na nekontrolované pro případ,
že by v budoucích verzích programu nastat mohly
► Při ošetřování výjimek, které nastat mohou,
ale nemají vliv na chod programu,
vložte do těla ošetření alespoň vysvětlující komentář
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
29
Zásady správného používání výjimek
2/2
► Používejte výjimky pouze k ošetření výjimečných stavů
► Kontrolované výjimky používejte u stavů, z nichž se lze zotavit,
jinak použijte výjimky nekontrolované
► Vyhýbejte se zbytečnému používání kontrolovaných výjimek
● Programátory ošetřování kontrolovaných výjimek obtěžuje
a mají pak tendenci je ošetřovat prázdným blokem catch
► Dávejte přednost standardním výjimkám,
vyvolávejte výjimky odpovídající dané abstrakci
● Programátoři by měli z názvu výjimky poznat, co se stalo
● Standardní výjimky mají všeobecně známý význam
► Snažte se o atomičnost selhání; i po vyhození výjimky
by měl být objekt v dobře definovaném stavu
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
30
Zásady správného používání výjimek
3/2
► Doplňujte výjimky zprávami,
výjimka by sama měla poskytnout dostatek informací
a neměla by programátora nutit k podrobnější analýze programu
► Dokumentujte vyvolávané výjimky v dokumentačních
komentářích pomocí značky @throws
► Nedělejte bloky try zbytečně velké,
kód uvnitř těchto bloků se neoptimalizuje
► Umíte-li výjimku v metodě ošetřit, udělejte to
► Detekuje-li se chyba v jedné metodě a má se ošetřit v jiné
(stejné či jiné instance), použijte výjimku.
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
31
Nejčastěji používané výjimky
1/2
► IllegalArgumentException
Byla zadána nepovolená hodnota parametru
● Např. chci nastavit zápornou velikost grafického tvaru
► IllegalStateException
V daném stavu objektu nelze metodu provést
● Např. otevřu soubor, přečtu pár vět, zavřu soubor a chci znovu přečíst větu
► NullPointerException
Byla vyvolána metoda instance, na níž ukazuje prázdný odkaz,
nebo byl předán nepovolený prázdný odkaz v parametru
► ArrayIndexOutOfBoundException
Byly zadány špatné meze pole, buď záporné nebo moc velké
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
32
Nejčastěji používané výjimky
2/2
► ConcurrentModificationException
V průběhu iterace byla změněna struktura kontejneru
● Např. byl do kontejneru přidán prvek
► NumberFormatException
Je požadován špatný převod řetězce na číslo či naopak
● Chci-li např. převést na číslo řetězec, který není číslem
● Častá chyba v metodách String.format či PrintStream.printf
► ClassCastException
Požadované přetypování není možné
► UnsupportedOperationException
Požadovaná operace není podporována
(např. chci přidat prvek do neměnného kontejneru)
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
33
Vaše jistota na trhu IT
Děkuji za pozornost
►Rudolf Pecinovský
http://vyuka.pecinovsky.cz/vse
mail: [email protected]
ICQ: 158 156 600
Slide 30
Vaše jistota na trhu IT
Výjimky
Rudolf Pecinovský
[email protected]
Vaše jistota na trhu IT
Obsah s odkazy
►Výjimky
►Výjimky kontrolované a nekontrolované
►Definice vlastních výjimek
Vaše jistota na trhu IT
Výjimky
►Výjimečné situace v programech
►Ošetření nestandardních situací v Javě
►Zpráva o výjimce
►Klíčová slova
►Činnost
►Vyvolání
Výjimečné situace v programech
► V každém programu je alespoň jedna chyba –
program na ni musí být připraven
► Starší programy
● Program vypsal chybové hlášení a ukončil činnost;
● V některých situacích (válcovací stolice, autopilot, …) nepřijatelné
● Funkce vrátí hodnotu signalizující chybu
● Programátor musí neustále testovat, co funkce vrací
● Knihovna měla pro tyto účely vyhrazenu speciální proměnnou,
do níž se v případě chyby zapsal její kód; nahlédnutím do proměnné
program zjistil kód poslední chyby
● Programátor musí neustále testovat, jaká je v proměnné hodnota
► Některé jazyky (Cobol, PL/1, …) proto přišly s koncepcí
ošetření nestandardních situací
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
4
Ošetření nestandardních situací v Javě
► Výjimečná událost =
problém, který brání dalšímu vykonávání části kódu
► Událost je výjimečná v tom, že na rozdíl od běžných problémů
nemá program k vyřešení situace dost informaci
► Program může při výskytu výjimečné události vyvolat výjimku
► Výjimka (exception)
objekt určený k přenosu informací o nastalém problému
z místa jeho vzniku do místa, kde bude problém řešen
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
5
Postup při vyvolání výjimky
1. Vytvoří se výjimka = objekt typu Throwable
(prakticky vždy instance některého z potomků)
2. Vytvořená výjimka se vyhodí =
přeruší se běh programu v místě, kde výjimka vznikla,
a začne se hledat místo, kde bude daná výjimka ošetřena
3. Ošetření výjimky (handler) by mělo uvést program do stavu,
v němž může jeho vykonávání pokračovat
► Výjimka „probublává“ programem z místa vyhození stále výše
a nenarazí-li cestou nikde na své ošetření,
zachytí ji virtuální stroj, který na standardní chybový výstup
vypíše zprávu o vzniku výjimky
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
6
Systémová zpráva o vzniku výjimky
Zpráva o vzniku výjimky spolu s názvem vlákna,
v němž k výjimce došlo (zde AWT-EventQueue-0)
Popis druhu výjimky (aritmetická výjimka dělení nulou)
Informace o místě, odkud byla volána metoda,
která vyvolala metodu, v níž došlo k vyhození výjimky
Informace o místě, odkud byla volána metoda,
v níž došlo k vyhození výjimky
Úplný název třídy včetně balíčku
Copyright © 2006, Rudolf Pecinovský
Název metody
VŠE – 05
Název souboru se
zdrojovým kódem
Číslo řádku zdrojáku,
kde došlo k výjimce
7
Klíčová slova související s výjimkami
► try (zkus)
Označuje blok kódu, v němž může dojít k výjimce
► throw (hoď)
Příkaz k vyhození výjimky;
musí být následován odkazem na existující instanci
► catch (chyť)
Blok ošetřující výjimku, která je zadána jako parametr
► finally (na konec)
Blok s povinnými závěrečnými akcemi nezávisejícími
na případném vzniku výjimky
► throws (hází)
Uvození seznamu výjimek vyhazovaných danou metodou
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
8
Vyvolání a ošetření výjimky v kódu
try {
//Kód, který může vyvolat výjimky
}
catch( Typ1 id1 ) {
//Ošetření výjimek typu Typ1
}
...
catch( TypN idN ) {
//ošetření výjimek typu TypN
}
finally {
//Kód, který se na závěr VŽDY provede
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
9
Náznak činnosti – řádný průběh
nedojde k vyvolání výjimky
= nedojde k chybě
try {
příkaz1();
příkaz2();
příkaz3();
}
catch ( xxxException e ) {
příkazProOšetřeníChyby();
}
Bloky catch
catch (…..
se přeskočí
finally {
ukončovacíPříkazy();
}
dalšíPříkaz();
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
12
Náznak činnosti – ošetřený výjimka
try {
příkaz1(); Při provádění metody příkaz2
dojde k ošetřené chybě
příkaz2();
příkaz3();
Byla vyhozena výjimka
tohoto typu nebo typu
}
některého z potomků
catch ( xxxException e ) {
příkazProOšetřeníChyby();
}
Ostatní bloky catch
catch (…..
se přeskočí
finally {
ukončovacíPříkazy();
}
dalšíPříkaz();
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
13
Náznak činnosti – neošetřená výjimka
Při provádění metody příkaz2
dojde k NEošetřené chybě
try {
příkaz1();
příkaz2();
příkaz3();
}
catch ( xxxException e ) {
příkazProOšetřeníChyby();
}
Ošetření nebylo nalezeno =>
catch (…..
provede se blok finally
a opouští se metoda
finally {
ukončovacíPříkazy();
}
dalšíPříkaz();
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
14
Vyvolání výjimky
public class Xyz implements Comparable
{
public bolean compareTo( Object o )
{
if( !(o instanceOf Xyz) )
throw new ClassCastException (
"\nPokus o porovnání s neporovnatelnou"
+ " instancí " + o );
//Zjištění, kdo je větší
return vysledek;
}
}
► Instanci nemusíme vytvářet až v příkazu throw,
můžeme ji vytvořit kdykoliv před tím a pak mu ji jen předat
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
15
Vaše jistota na trhu IT
Výjimky kontrolované a
nekontrolované
►Hierarchie výjimek
►Pořadí výjimek v blocích catch
►Metody generující výjimky
►Metody třídy Throwable
►Zřetězené výjimky
►Převod kontrolovaných na nekontrolované
Charakteristika
► Výjimky, které jsou potomky třídy RuntimeException
nebo Error označujeme jako nekontrolované (unchecked),
protože překladač nekontroluje, zda je na ně program připraven
► Ostatní výjimky označujeme jako kontrolované (checked),
protože překladač kontroluje dodržení pravidel:
● Každá metoda, která může vyhodit kontrolovanou výjimku,
se musí k této skutečnosti veřejně přihlásit
● Každé použití metody, která může vyhodit kontrolovanou výjimku,
musí být buď uzavřeno v bloku try…catch,
nebo se volající metoda musí přihlásit k tomu,
že může také vyhodit danou kontrolovanou výjimku
► Nekontrolované výjimky ohlašují chyby v programu,
kontrolované výjimky očekávatelné situace,
na jejichž výskyt má být program připraven
a měl by na ně umět reagovat
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
17
Hierarchie výjimek
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
18
Pořadí výjimek v blocích catch
► Třída NumberFormatException
je potomkem třídy RuntimeException
try {
Syntaktická chyba,
......
na druhý blok catch nikdy nedojde
}
catch (RuntimeException e) {
.........
}
Obrácené pořadí bloků catch
catch (NumberFormatException e){
vše vyřeší
........
try {
}
......
}
catch (NumberFormatException e) {
.........
}
catch (RuntimeException e){
........
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
19
Metody generující výjimky
► Java vyžaduje, aby programy, které používají metody
schopné vyvolat kontrolované výjimky,
byly o této schopnosti používaných metod informovány =>
pak vědí, které výjimku musí umět zachytit a ošetřit
► Všechny kontrolované výjimky, které může metoda vyhodit,
musí deklarovat v hlavičce za klíčovým slovem throws
► Deklarace vyhazování nekontrolovaných výjimek není povinná
public void metoda()
throws KontrolovanáVýjimka1,
KontrolovanáVýjimka2
{
// Tělo metody
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
20
Metody třídy Throwable
► String getMessage()
Vrátí zprávu popisující danou výjimku
► String toString()
Vrátí název třídy výjimky následovaný případnou zprávou
► void printStackTrace()
Vytiskne toString() následovaný sadou informací o volající
posloupnosti, která vedla k vzniku výjimky
► Throwable fillInStackTrace()
Připraví nové informace o volací posloupnosti
vedoucí k místu zavolání této metody
► StackTraceElement[] getStackTrace()
Vrátí uchované informace o volací posloupnosti dané výjimky
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
21
Zřetězené výjimky
► V některých situacích je vhodné v rámci ošetření výjimky vyvolat
jinou výjimku, a přitom umožnit zjistit,
která výjimka byla prvotním hybatelem celé akce
► Řada výjimek má mezi svými konstruktory i takové,
které akceptují jako poslední parametr
odkaz na výjimku, jež byla příčinou vyvolání dané výjimky
► Chce-li se program zeptat výjimky na výjimku, která ji způsobila,
použije metodu
public Throwable getCause()
► Ve zprávě o vyvolání výjimky jsou místa, kde byla jedna výjimka
nahrazena jinou, označována textem caused by:
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
22
Ukázka výpisu při zřetězení výjimek
HighLevelException: MidLevelException: LowLevelException
at Junk.a(Junk.java:13)
at Junk.main(Junk.java:4)
Caused by: MidLevelException: LowLevelException
at Junk.c(Junk.java:23)
at Junk.b(Junk.java:17)
at Junk.a(Junk.java:11)
... 1 more
Caused by: LowLevelException
at Junk.e(Junk.java:30)
at Junk.d(Junk.java:27)
at Junk.c(Junk.java:21)
... 3 more
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
23
Převod kontrolovaných na nekontrolované
► Ošetřování kontrolovaných výjimek obtěžuje
► Víme-li, že k dané výjimce nejspíš nedojde
a ošetřujeme-li ji pouze proto, že na tom překladač trvá,
můžeme pro případ, že by k výjimce přece jenom došlo
zaměnit kontrolovanou výjimku za nekontrolovanou
public void prevod( String s ) {
try {
prověř( s );
} catch( Exception ex ) {
throw new RuntimeException( " Neprověřeno! ", ex );
}
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
24
Vaše jistota na trhu IT
Definice vlastních výjimek
►Hierarchie výjimek
►Pořadí výjimek v blocích catch
►Metody generující výjimky
►Metody třídy Throwable
►Vlastní výjimky
►Zásady správného používání výjimek
Definice vlastních výjimek
► Výjimky jsou zcela běžné třídy;
považujeme-li to proto za vhodné, můžeme definovat i vlastní
► Před definicí nové výjimky bychom si měli ujasnit,
bude-li kontrolovaná či nekontrolovaná;
podle toho definujeme jejího předka
► Název výjimek končí dle konvencí slovem Exception
před nímž je naznačena podstata dané výjimky
● IllegalArgumetnException
● NoSuchMethodException
● BadStringOperationException
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
26
Příklad vlastní kontrolované výjimky
public class VelkýPrůšvihException
extends Exception
{
public VelkýPrůšvihException() {};
public VelkýPrůšvihException( String zpráva ) {
super( zpráva );
}
public VelkýPrůšvihException(String zpráva,
Throwable původce ) {
super( zpráva, původce );
}
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
27
Test správného vyhození výjimky
► Na vytvářených programech je třeba otestovat i to,
že v definovaných situacích vyhodí požadovanou výjimku
public void testVyhozeníVýjimky()
{
try {
metodaKteráMáVyhoditVýjimku();
} catch ( VelkýPrůšvihException vpe ) {
return;
}
fail( "Nebyla vyhozena výjimka VelkýPrůšvihException" );
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
28
Zásady správného používání výjimek
1/2
Neignorujte
výjimky
try {
//Nějaký kód
}
catch(Exception e){}
► Výjimky, o nichž víte, že nemohou nastat,
převeďte na nekontrolované pro případ,
že by v budoucích verzích programu nastat mohly
► Při ošetřování výjimek, které nastat mohou,
ale nemají vliv na chod programu,
vložte do těla ošetření alespoň vysvětlující komentář
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
29
Zásady správného používání výjimek
2/2
► Používejte výjimky pouze k ošetření výjimečných stavů
► Kontrolované výjimky používejte u stavů, z nichž se lze zotavit,
jinak použijte výjimky nekontrolované
► Vyhýbejte se zbytečnému používání kontrolovaných výjimek
● Programátory ošetřování kontrolovaných výjimek obtěžuje
a mají pak tendenci je ošetřovat prázdným blokem catch
► Dávejte přednost standardním výjimkám,
vyvolávejte výjimky odpovídající dané abstrakci
● Programátoři by měli z názvu výjimky poznat, co se stalo
● Standardní výjimky mají všeobecně známý význam
► Snažte se o atomičnost selhání; i po vyhození výjimky
by měl být objekt v dobře definovaném stavu
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
30
Zásady správného používání výjimek
3/2
► Doplňujte výjimky zprávami,
výjimka by sama měla poskytnout dostatek informací
a neměla by programátora nutit k podrobnější analýze programu
► Dokumentujte vyvolávané výjimky v dokumentačních
komentářích pomocí značky @throws
► Nedělejte bloky try zbytečně velké,
kód uvnitř těchto bloků se neoptimalizuje
► Umíte-li výjimku v metodě ošetřit, udělejte to
► Detekuje-li se chyba v jedné metodě a má se ošetřit v jiné
(stejné či jiné instance), použijte výjimku.
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
31
Nejčastěji používané výjimky
1/2
► IllegalArgumentException
Byla zadána nepovolená hodnota parametru
● Např. chci nastavit zápornou velikost grafického tvaru
► IllegalStateException
V daném stavu objektu nelze metodu provést
● Např. otevřu soubor, přečtu pár vět, zavřu soubor a chci znovu přečíst větu
► NullPointerException
Byla vyvolána metoda instance, na níž ukazuje prázdný odkaz,
nebo byl předán nepovolený prázdný odkaz v parametru
► ArrayIndexOutOfBoundException
Byly zadány špatné meze pole, buď záporné nebo moc velké
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
32
Nejčastěji používané výjimky
2/2
► ConcurrentModificationException
V průběhu iterace byla změněna struktura kontejneru
● Např. byl do kontejneru přidán prvek
► NumberFormatException
Je požadován špatný převod řetězce na číslo či naopak
● Chci-li např. převést na číslo řetězec, který není číslem
● Častá chyba v metodách String.format či PrintStream.printf
► ClassCastException
Požadované přetypování není možné
► UnsupportedOperationException
Požadovaná operace není podporována
(např. chci přidat prvek do neměnného kontejneru)
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
33
Vaše jistota na trhu IT
Děkuji za pozornost
►Rudolf Pecinovský
http://vyuka.pecinovsky.cz/vse
mail: [email protected]
ICQ: 158 156 600
Slide 31
Vaše jistota na trhu IT
Výjimky
Rudolf Pecinovský
[email protected]
Vaše jistota na trhu IT
Obsah s odkazy
►Výjimky
►Výjimky kontrolované a nekontrolované
►Definice vlastních výjimek
Vaše jistota na trhu IT
Výjimky
►Výjimečné situace v programech
►Ošetření nestandardních situací v Javě
►Zpráva o výjimce
►Klíčová slova
►Činnost
►Vyvolání
Výjimečné situace v programech
► V každém programu je alespoň jedna chyba –
program na ni musí být připraven
► Starší programy
● Program vypsal chybové hlášení a ukončil činnost;
● V některých situacích (válcovací stolice, autopilot, …) nepřijatelné
● Funkce vrátí hodnotu signalizující chybu
● Programátor musí neustále testovat, co funkce vrací
● Knihovna měla pro tyto účely vyhrazenu speciální proměnnou,
do níž se v případě chyby zapsal její kód; nahlédnutím do proměnné
program zjistil kód poslední chyby
● Programátor musí neustále testovat, jaká je v proměnné hodnota
► Některé jazyky (Cobol, PL/1, …) proto přišly s koncepcí
ošetření nestandardních situací
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
4
Ošetření nestandardních situací v Javě
► Výjimečná událost =
problém, který brání dalšímu vykonávání části kódu
► Událost je výjimečná v tom, že na rozdíl od běžných problémů
nemá program k vyřešení situace dost informaci
► Program může při výskytu výjimečné události vyvolat výjimku
► Výjimka (exception)
objekt určený k přenosu informací o nastalém problému
z místa jeho vzniku do místa, kde bude problém řešen
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
5
Postup při vyvolání výjimky
1. Vytvoří se výjimka = objekt typu Throwable
(prakticky vždy instance některého z potomků)
2. Vytvořená výjimka se vyhodí =
přeruší se běh programu v místě, kde výjimka vznikla,
a začne se hledat místo, kde bude daná výjimka ošetřena
3. Ošetření výjimky (handler) by mělo uvést program do stavu,
v němž může jeho vykonávání pokračovat
► Výjimka „probublává“ programem z místa vyhození stále výše
a nenarazí-li cestou nikde na své ošetření,
zachytí ji virtuální stroj, který na standardní chybový výstup
vypíše zprávu o vzniku výjimky
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
6
Systémová zpráva o vzniku výjimky
Zpráva o vzniku výjimky spolu s názvem vlákna,
v němž k výjimce došlo (zde AWT-EventQueue-0)
Popis druhu výjimky (aritmetická výjimka dělení nulou)
Informace o místě, odkud byla volána metoda,
která vyvolala metodu, v níž došlo k vyhození výjimky
Informace o místě, odkud byla volána metoda,
v níž došlo k vyhození výjimky
Úplný název třídy včetně balíčku
Copyright © 2006, Rudolf Pecinovský
Název metody
VŠE – 05
Název souboru se
zdrojovým kódem
Číslo řádku zdrojáku,
kde došlo k výjimce
7
Klíčová slova související s výjimkami
► try (zkus)
Označuje blok kódu, v němž může dojít k výjimce
► throw (hoď)
Příkaz k vyhození výjimky;
musí být následován odkazem na existující instanci
► catch (chyť)
Blok ošetřující výjimku, která je zadána jako parametr
► finally (na konec)
Blok s povinnými závěrečnými akcemi nezávisejícími
na případném vzniku výjimky
► throws (hází)
Uvození seznamu výjimek vyhazovaných danou metodou
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
8
Vyvolání a ošetření výjimky v kódu
try {
//Kód, který může vyvolat výjimky
}
catch( Typ1 id1 ) {
//Ošetření výjimek typu Typ1
}
...
catch( TypN idN ) {
//ošetření výjimek typu TypN
}
finally {
//Kód, který se na závěr VŽDY provede
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
9
Náznak činnosti – řádný průběh
nedojde k vyvolání výjimky
= nedojde k chybě
try {
příkaz1();
příkaz2();
příkaz3();
}
catch ( xxxException e ) {
příkazProOšetřeníChyby();
}
Bloky catch
catch (…..
se přeskočí
finally {
ukončovacíPříkazy();
}
dalšíPříkaz();
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
12
Náznak činnosti – ošetřený výjimka
try {
příkaz1(); Při provádění metody příkaz2
dojde k ošetřené chybě
příkaz2();
příkaz3();
Byla vyhozena výjimka
tohoto typu nebo typu
}
některého z potomků
catch ( xxxException e ) {
příkazProOšetřeníChyby();
}
Ostatní bloky catch
catch (…..
se přeskočí
finally {
ukončovacíPříkazy();
}
dalšíPříkaz();
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
13
Náznak činnosti – neošetřená výjimka
Při provádění metody příkaz2
dojde k NEošetřené chybě
try {
příkaz1();
příkaz2();
příkaz3();
}
catch ( xxxException e ) {
příkazProOšetřeníChyby();
}
Ošetření nebylo nalezeno =>
catch (…..
provede se blok finally
a opouští se metoda
finally {
ukončovacíPříkazy();
}
dalšíPříkaz();
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
14
Vyvolání výjimky
public class Xyz implements Comparable
{
public bolean compareTo( Object o )
{
if( !(o instanceOf Xyz) )
throw new ClassCastException (
"\nPokus o porovnání s neporovnatelnou"
+ " instancí " + o );
//Zjištění, kdo je větší
return vysledek;
}
}
► Instanci nemusíme vytvářet až v příkazu throw,
můžeme ji vytvořit kdykoliv před tím a pak mu ji jen předat
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
15
Vaše jistota na trhu IT
Výjimky kontrolované a
nekontrolované
►Hierarchie výjimek
►Pořadí výjimek v blocích catch
►Metody generující výjimky
►Metody třídy Throwable
►Zřetězené výjimky
►Převod kontrolovaných na nekontrolované
Charakteristika
► Výjimky, které jsou potomky třídy RuntimeException
nebo Error označujeme jako nekontrolované (unchecked),
protože překladač nekontroluje, zda je na ně program připraven
► Ostatní výjimky označujeme jako kontrolované (checked),
protože překladač kontroluje dodržení pravidel:
● Každá metoda, která může vyhodit kontrolovanou výjimku,
se musí k této skutečnosti veřejně přihlásit
● Každé použití metody, která může vyhodit kontrolovanou výjimku,
musí být buď uzavřeno v bloku try…catch,
nebo se volající metoda musí přihlásit k tomu,
že může také vyhodit danou kontrolovanou výjimku
► Nekontrolované výjimky ohlašují chyby v programu,
kontrolované výjimky očekávatelné situace,
na jejichž výskyt má být program připraven
a měl by na ně umět reagovat
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
17
Hierarchie výjimek
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
18
Pořadí výjimek v blocích catch
► Třída NumberFormatException
je potomkem třídy RuntimeException
try {
Syntaktická chyba,
......
na druhý blok catch nikdy nedojde
}
catch (RuntimeException e) {
.........
}
Obrácené pořadí bloků catch
catch (NumberFormatException e){
vše vyřeší
........
try {
}
......
}
catch (NumberFormatException e) {
.........
}
catch (RuntimeException e){
........
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
19
Metody generující výjimky
► Java vyžaduje, aby programy, které používají metody
schopné vyvolat kontrolované výjimky,
byly o této schopnosti používaných metod informovány =>
pak vědí, které výjimku musí umět zachytit a ošetřit
► Všechny kontrolované výjimky, které může metoda vyhodit,
musí deklarovat v hlavičce za klíčovým slovem throws
► Deklarace vyhazování nekontrolovaných výjimek není povinná
public void metoda()
throws KontrolovanáVýjimka1,
KontrolovanáVýjimka2
{
// Tělo metody
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
20
Metody třídy Throwable
► String getMessage()
Vrátí zprávu popisující danou výjimku
► String toString()
Vrátí název třídy výjimky následovaný případnou zprávou
► void printStackTrace()
Vytiskne toString() následovaný sadou informací o volající
posloupnosti, která vedla k vzniku výjimky
► Throwable fillInStackTrace()
Připraví nové informace o volací posloupnosti
vedoucí k místu zavolání této metody
► StackTraceElement[] getStackTrace()
Vrátí uchované informace o volací posloupnosti dané výjimky
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
21
Zřetězené výjimky
► V některých situacích je vhodné v rámci ošetření výjimky vyvolat
jinou výjimku, a přitom umožnit zjistit,
která výjimka byla prvotním hybatelem celé akce
► Řada výjimek má mezi svými konstruktory i takové,
které akceptují jako poslední parametr
odkaz na výjimku, jež byla příčinou vyvolání dané výjimky
► Chce-li se program zeptat výjimky na výjimku, která ji způsobila,
použije metodu
public Throwable getCause()
► Ve zprávě o vyvolání výjimky jsou místa, kde byla jedna výjimka
nahrazena jinou, označována textem caused by:
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
22
Ukázka výpisu při zřetězení výjimek
HighLevelException: MidLevelException: LowLevelException
at Junk.a(Junk.java:13)
at Junk.main(Junk.java:4)
Caused by: MidLevelException: LowLevelException
at Junk.c(Junk.java:23)
at Junk.b(Junk.java:17)
at Junk.a(Junk.java:11)
... 1 more
Caused by: LowLevelException
at Junk.e(Junk.java:30)
at Junk.d(Junk.java:27)
at Junk.c(Junk.java:21)
... 3 more
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
23
Převod kontrolovaných na nekontrolované
► Ošetřování kontrolovaných výjimek obtěžuje
► Víme-li, že k dané výjimce nejspíš nedojde
a ošetřujeme-li ji pouze proto, že na tom překladač trvá,
můžeme pro případ, že by k výjimce přece jenom došlo
zaměnit kontrolovanou výjimku za nekontrolovanou
public void prevod( String s ) {
try {
prověř( s );
} catch( Exception ex ) {
throw new RuntimeException( " Neprověřeno! ", ex );
}
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
24
Vaše jistota na trhu IT
Definice vlastních výjimek
►Hierarchie výjimek
►Pořadí výjimek v blocích catch
►Metody generující výjimky
►Metody třídy Throwable
►Vlastní výjimky
►Zásady správného používání výjimek
Definice vlastních výjimek
► Výjimky jsou zcela běžné třídy;
považujeme-li to proto za vhodné, můžeme definovat i vlastní
► Před definicí nové výjimky bychom si měli ujasnit,
bude-li kontrolovaná či nekontrolovaná;
podle toho definujeme jejího předka
► Název výjimek končí dle konvencí slovem Exception
před nímž je naznačena podstata dané výjimky
● IllegalArgumetnException
● NoSuchMethodException
● BadStringOperationException
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
26
Příklad vlastní kontrolované výjimky
public class VelkýPrůšvihException
extends Exception
{
public VelkýPrůšvihException() {};
public VelkýPrůšvihException( String zpráva ) {
super( zpráva );
}
public VelkýPrůšvihException(String zpráva,
Throwable původce ) {
super( zpráva, původce );
}
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
27
Test správného vyhození výjimky
► Na vytvářených programech je třeba otestovat i to,
že v definovaných situacích vyhodí požadovanou výjimku
public void testVyhozeníVýjimky()
{
try {
metodaKteráMáVyhoditVýjimku();
} catch ( VelkýPrůšvihException vpe ) {
return;
}
fail( "Nebyla vyhozena výjimka VelkýPrůšvihException" );
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
28
Zásady správného používání výjimek
1/2
Neignorujte
výjimky
try {
//Nějaký kód
}
catch(Exception e){}
► Výjimky, o nichž víte, že nemohou nastat,
převeďte na nekontrolované pro případ,
že by v budoucích verzích programu nastat mohly
► Při ošetřování výjimek, které nastat mohou,
ale nemají vliv na chod programu,
vložte do těla ošetření alespoň vysvětlující komentář
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
29
Zásady správného používání výjimek
2/2
► Používejte výjimky pouze k ošetření výjimečných stavů
► Kontrolované výjimky používejte u stavů, z nichž se lze zotavit,
jinak použijte výjimky nekontrolované
► Vyhýbejte se zbytečnému používání kontrolovaných výjimek
● Programátory ošetřování kontrolovaných výjimek obtěžuje
a mají pak tendenci je ošetřovat prázdným blokem catch
► Dávejte přednost standardním výjimkám,
vyvolávejte výjimky odpovídající dané abstrakci
● Programátoři by měli z názvu výjimky poznat, co se stalo
● Standardní výjimky mají všeobecně známý význam
► Snažte se o atomičnost selhání; i po vyhození výjimky
by měl být objekt v dobře definovaném stavu
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
30
Zásady správného používání výjimek
3/2
► Doplňujte výjimky zprávami,
výjimka by sama měla poskytnout dostatek informací
a neměla by programátora nutit k podrobnější analýze programu
► Dokumentujte vyvolávané výjimky v dokumentačních
komentářích pomocí značky @throws
► Nedělejte bloky try zbytečně velké,
kód uvnitř těchto bloků se neoptimalizuje
► Umíte-li výjimku v metodě ošetřit, udělejte to
► Detekuje-li se chyba v jedné metodě a má se ošetřit v jiné
(stejné či jiné instance), použijte výjimku.
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
31
Nejčastěji používané výjimky
1/2
► IllegalArgumentException
Byla zadána nepovolená hodnota parametru
● Např. chci nastavit zápornou velikost grafického tvaru
► IllegalStateException
V daném stavu objektu nelze metodu provést
● Např. otevřu soubor, přečtu pár vět, zavřu soubor a chci znovu přečíst větu
► NullPointerException
Byla vyvolána metoda instance, na níž ukazuje prázdný odkaz,
nebo byl předán nepovolený prázdný odkaz v parametru
► ArrayIndexOutOfBoundException
Byly zadány špatné meze pole, buď záporné nebo moc velké
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
32
Nejčastěji používané výjimky
2/2
► ConcurrentModificationException
V průběhu iterace byla změněna struktura kontejneru
● Např. byl do kontejneru přidán prvek
► NumberFormatException
Je požadován špatný převod řetězce na číslo či naopak
● Chci-li např. převést na číslo řetězec, který není číslem
● Častá chyba v metodách String.format či PrintStream.printf
► ClassCastException
Požadované přetypování není možné
► UnsupportedOperationException
Požadovaná operace není podporována
(např. chci přidat prvek do neměnného kontejneru)
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
33
Vaše jistota na trhu IT
Děkuji za pozornost
►Rudolf Pecinovský
http://vyuka.pecinovsky.cz/vse
mail: [email protected]
ICQ: 158 156 600
Slide 32
Vaše jistota na trhu IT
Výjimky
Rudolf Pecinovský
[email protected]
Vaše jistota na trhu IT
Obsah s odkazy
►Výjimky
►Výjimky kontrolované a nekontrolované
►Definice vlastních výjimek
Vaše jistota na trhu IT
Výjimky
►Výjimečné situace v programech
►Ošetření nestandardních situací v Javě
►Zpráva o výjimce
►Klíčová slova
►Činnost
►Vyvolání
Výjimečné situace v programech
► V každém programu je alespoň jedna chyba –
program na ni musí být připraven
► Starší programy
● Program vypsal chybové hlášení a ukončil činnost;
● V některých situacích (válcovací stolice, autopilot, …) nepřijatelné
● Funkce vrátí hodnotu signalizující chybu
● Programátor musí neustále testovat, co funkce vrací
● Knihovna měla pro tyto účely vyhrazenu speciální proměnnou,
do níž se v případě chyby zapsal její kód; nahlédnutím do proměnné
program zjistil kód poslední chyby
● Programátor musí neustále testovat, jaká je v proměnné hodnota
► Některé jazyky (Cobol, PL/1, …) proto přišly s koncepcí
ošetření nestandardních situací
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
4
Ošetření nestandardních situací v Javě
► Výjimečná událost =
problém, který brání dalšímu vykonávání části kódu
► Událost je výjimečná v tom, že na rozdíl od běžných problémů
nemá program k vyřešení situace dost informaci
► Program může při výskytu výjimečné události vyvolat výjimku
► Výjimka (exception)
objekt určený k přenosu informací o nastalém problému
z místa jeho vzniku do místa, kde bude problém řešen
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
5
Postup při vyvolání výjimky
1. Vytvoří se výjimka = objekt typu Throwable
(prakticky vždy instance některého z potomků)
2. Vytvořená výjimka se vyhodí =
přeruší se běh programu v místě, kde výjimka vznikla,
a začne se hledat místo, kde bude daná výjimka ošetřena
3. Ošetření výjimky (handler) by mělo uvést program do stavu,
v němž může jeho vykonávání pokračovat
► Výjimka „probublává“ programem z místa vyhození stále výše
a nenarazí-li cestou nikde na své ošetření,
zachytí ji virtuální stroj, který na standardní chybový výstup
vypíše zprávu o vzniku výjimky
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
6
Systémová zpráva o vzniku výjimky
Zpráva o vzniku výjimky spolu s názvem vlákna,
v němž k výjimce došlo (zde AWT-EventQueue-0)
Popis druhu výjimky (aritmetická výjimka dělení nulou)
Informace o místě, odkud byla volána metoda,
která vyvolala metodu, v níž došlo k vyhození výjimky
Informace o místě, odkud byla volána metoda,
v níž došlo k vyhození výjimky
Úplný název třídy včetně balíčku
Copyright © 2006, Rudolf Pecinovský
Název metody
VŠE – 05
Název souboru se
zdrojovým kódem
Číslo řádku zdrojáku,
kde došlo k výjimce
7
Klíčová slova související s výjimkami
► try (zkus)
Označuje blok kódu, v němž může dojít k výjimce
► throw (hoď)
Příkaz k vyhození výjimky;
musí být následován odkazem na existující instanci
► catch (chyť)
Blok ošetřující výjimku, která je zadána jako parametr
► finally (na konec)
Blok s povinnými závěrečnými akcemi nezávisejícími
na případném vzniku výjimky
► throws (hází)
Uvození seznamu výjimek vyhazovaných danou metodou
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
8
Vyvolání a ošetření výjimky v kódu
try {
//Kód, který může vyvolat výjimky
}
catch( Typ1 id1 ) {
//Ošetření výjimek typu Typ1
}
...
catch( TypN idN ) {
//ošetření výjimek typu TypN
}
finally {
//Kód, který se na závěr VŽDY provede
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
9
Náznak činnosti – řádný průběh
nedojde k vyvolání výjimky
= nedojde k chybě
try {
příkaz1();
příkaz2();
příkaz3();
}
catch ( xxxException e ) {
příkazProOšetřeníChyby();
}
Bloky catch
catch (…..
se přeskočí
finally {
ukončovacíPříkazy();
}
dalšíPříkaz();
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
12
Náznak činnosti – ošetřený výjimka
try {
příkaz1(); Při provádění metody příkaz2
dojde k ošetřené chybě
příkaz2();
příkaz3();
Byla vyhozena výjimka
tohoto typu nebo typu
}
některého z potomků
catch ( xxxException e ) {
příkazProOšetřeníChyby();
}
Ostatní bloky catch
catch (…..
se přeskočí
finally {
ukončovacíPříkazy();
}
dalšíPříkaz();
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
13
Náznak činnosti – neošetřená výjimka
Při provádění metody příkaz2
dojde k NEošetřené chybě
try {
příkaz1();
příkaz2();
příkaz3();
}
catch ( xxxException e ) {
příkazProOšetřeníChyby();
}
Ošetření nebylo nalezeno =>
catch (…..
provede se blok finally
a opouští se metoda
finally {
ukončovacíPříkazy();
}
dalšíPříkaz();
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
14
Vyvolání výjimky
public class Xyz implements Comparable
{
public bolean compareTo( Object o )
{
if( !(o instanceOf Xyz) )
throw new ClassCastException (
"\nPokus o porovnání s neporovnatelnou"
+ " instancí " + o );
//Zjištění, kdo je větší
return vysledek;
}
}
► Instanci nemusíme vytvářet až v příkazu throw,
můžeme ji vytvořit kdykoliv před tím a pak mu ji jen předat
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
15
Vaše jistota na trhu IT
Výjimky kontrolované a
nekontrolované
►Hierarchie výjimek
►Pořadí výjimek v blocích catch
►Metody generující výjimky
►Metody třídy Throwable
►Zřetězené výjimky
►Převod kontrolovaných na nekontrolované
Charakteristika
► Výjimky, které jsou potomky třídy RuntimeException
nebo Error označujeme jako nekontrolované (unchecked),
protože překladač nekontroluje, zda je na ně program připraven
► Ostatní výjimky označujeme jako kontrolované (checked),
protože překladač kontroluje dodržení pravidel:
● Každá metoda, která může vyhodit kontrolovanou výjimku,
se musí k této skutečnosti veřejně přihlásit
● Každé použití metody, která může vyhodit kontrolovanou výjimku,
musí být buď uzavřeno v bloku try…catch,
nebo se volající metoda musí přihlásit k tomu,
že může také vyhodit danou kontrolovanou výjimku
► Nekontrolované výjimky ohlašují chyby v programu,
kontrolované výjimky očekávatelné situace,
na jejichž výskyt má být program připraven
a měl by na ně umět reagovat
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
17
Hierarchie výjimek
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
18
Pořadí výjimek v blocích catch
► Třída NumberFormatException
je potomkem třídy RuntimeException
try {
Syntaktická chyba,
......
na druhý blok catch nikdy nedojde
}
catch (RuntimeException e) {
.........
}
Obrácené pořadí bloků catch
catch (NumberFormatException e){
vše vyřeší
........
try {
}
......
}
catch (NumberFormatException e) {
.........
}
catch (RuntimeException e){
........
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
19
Metody generující výjimky
► Java vyžaduje, aby programy, které používají metody
schopné vyvolat kontrolované výjimky,
byly o této schopnosti používaných metod informovány =>
pak vědí, které výjimku musí umět zachytit a ošetřit
► Všechny kontrolované výjimky, které může metoda vyhodit,
musí deklarovat v hlavičce za klíčovým slovem throws
► Deklarace vyhazování nekontrolovaných výjimek není povinná
public void metoda()
throws KontrolovanáVýjimka1,
KontrolovanáVýjimka2
{
// Tělo metody
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
20
Metody třídy Throwable
► String getMessage()
Vrátí zprávu popisující danou výjimku
► String toString()
Vrátí název třídy výjimky následovaný případnou zprávou
► void printStackTrace()
Vytiskne toString() následovaný sadou informací o volající
posloupnosti, která vedla k vzniku výjimky
► Throwable fillInStackTrace()
Připraví nové informace o volací posloupnosti
vedoucí k místu zavolání této metody
► StackTraceElement[] getStackTrace()
Vrátí uchované informace o volací posloupnosti dané výjimky
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
21
Zřetězené výjimky
► V některých situacích je vhodné v rámci ošetření výjimky vyvolat
jinou výjimku, a přitom umožnit zjistit,
která výjimka byla prvotním hybatelem celé akce
► Řada výjimek má mezi svými konstruktory i takové,
které akceptují jako poslední parametr
odkaz na výjimku, jež byla příčinou vyvolání dané výjimky
► Chce-li se program zeptat výjimky na výjimku, která ji způsobila,
použije metodu
public Throwable getCause()
► Ve zprávě o vyvolání výjimky jsou místa, kde byla jedna výjimka
nahrazena jinou, označována textem caused by:
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
22
Ukázka výpisu při zřetězení výjimek
HighLevelException: MidLevelException: LowLevelException
at Junk.a(Junk.java:13)
at Junk.main(Junk.java:4)
Caused by: MidLevelException: LowLevelException
at Junk.c(Junk.java:23)
at Junk.b(Junk.java:17)
at Junk.a(Junk.java:11)
... 1 more
Caused by: LowLevelException
at Junk.e(Junk.java:30)
at Junk.d(Junk.java:27)
at Junk.c(Junk.java:21)
... 3 more
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
23
Převod kontrolovaných na nekontrolované
► Ošetřování kontrolovaných výjimek obtěžuje
► Víme-li, že k dané výjimce nejspíš nedojde
a ošetřujeme-li ji pouze proto, že na tom překladač trvá,
můžeme pro případ, že by k výjimce přece jenom došlo
zaměnit kontrolovanou výjimku za nekontrolovanou
public void prevod( String s ) {
try {
prověř( s );
} catch( Exception ex ) {
throw new RuntimeException( " Neprověřeno! ", ex );
}
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
24
Vaše jistota na trhu IT
Definice vlastních výjimek
►Hierarchie výjimek
►Pořadí výjimek v blocích catch
►Metody generující výjimky
►Metody třídy Throwable
►Vlastní výjimky
►Zásady správného používání výjimek
Definice vlastních výjimek
► Výjimky jsou zcela běžné třídy;
považujeme-li to proto za vhodné, můžeme definovat i vlastní
► Před definicí nové výjimky bychom si měli ujasnit,
bude-li kontrolovaná či nekontrolovaná;
podle toho definujeme jejího předka
► Název výjimek končí dle konvencí slovem Exception
před nímž je naznačena podstata dané výjimky
● IllegalArgumetnException
● NoSuchMethodException
● BadStringOperationException
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
26
Příklad vlastní kontrolované výjimky
public class VelkýPrůšvihException
extends Exception
{
public VelkýPrůšvihException() {};
public VelkýPrůšvihException( String zpráva ) {
super( zpráva );
}
public VelkýPrůšvihException(String zpráva,
Throwable původce ) {
super( zpráva, původce );
}
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
27
Test správného vyhození výjimky
► Na vytvářených programech je třeba otestovat i to,
že v definovaných situacích vyhodí požadovanou výjimku
public void testVyhozeníVýjimky()
{
try {
metodaKteráMáVyhoditVýjimku();
} catch ( VelkýPrůšvihException vpe ) {
return;
}
fail( "Nebyla vyhozena výjimka VelkýPrůšvihException" );
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
28
Zásady správného používání výjimek
1/2
Neignorujte
výjimky
try {
//Nějaký kód
}
catch(Exception e){}
► Výjimky, o nichž víte, že nemohou nastat,
převeďte na nekontrolované pro případ,
že by v budoucích verzích programu nastat mohly
► Při ošetřování výjimek, které nastat mohou,
ale nemají vliv na chod programu,
vložte do těla ošetření alespoň vysvětlující komentář
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
29
Zásady správného používání výjimek
2/2
► Používejte výjimky pouze k ošetření výjimečných stavů
► Kontrolované výjimky používejte u stavů, z nichž se lze zotavit,
jinak použijte výjimky nekontrolované
► Vyhýbejte se zbytečnému používání kontrolovaných výjimek
● Programátory ošetřování kontrolovaných výjimek obtěžuje
a mají pak tendenci je ošetřovat prázdným blokem catch
► Dávejte přednost standardním výjimkám,
vyvolávejte výjimky odpovídající dané abstrakci
● Programátoři by měli z názvu výjimky poznat, co se stalo
● Standardní výjimky mají všeobecně známý význam
► Snažte se o atomičnost selhání; i po vyhození výjimky
by měl být objekt v dobře definovaném stavu
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
30
Zásady správného používání výjimek
3/2
► Doplňujte výjimky zprávami,
výjimka by sama měla poskytnout dostatek informací
a neměla by programátora nutit k podrobnější analýze programu
► Dokumentujte vyvolávané výjimky v dokumentačních
komentářích pomocí značky @throws
► Nedělejte bloky try zbytečně velké,
kód uvnitř těchto bloků se neoptimalizuje
► Umíte-li výjimku v metodě ošetřit, udělejte to
► Detekuje-li se chyba v jedné metodě a má se ošetřit v jiné
(stejné či jiné instance), použijte výjimku.
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
31
Nejčastěji používané výjimky
1/2
► IllegalArgumentException
Byla zadána nepovolená hodnota parametru
● Např. chci nastavit zápornou velikost grafického tvaru
► IllegalStateException
V daném stavu objektu nelze metodu provést
● Např. otevřu soubor, přečtu pár vět, zavřu soubor a chci znovu přečíst větu
► NullPointerException
Byla vyvolána metoda instance, na níž ukazuje prázdný odkaz,
nebo byl předán nepovolený prázdný odkaz v parametru
► ArrayIndexOutOfBoundException
Byly zadány špatné meze pole, buď záporné nebo moc velké
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
32
Nejčastěji používané výjimky
2/2
► ConcurrentModificationException
V průběhu iterace byla změněna struktura kontejneru
● Např. byl do kontejneru přidán prvek
► NumberFormatException
Je požadován špatný převod řetězce na číslo či naopak
● Chci-li např. převést na číslo řetězec, který není číslem
● Častá chyba v metodách String.format či PrintStream.printf
► ClassCastException
Požadované přetypování není možné
► UnsupportedOperationException
Požadovaná operace není podporována
(např. chci přidat prvek do neměnného kontejneru)
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
33
Vaše jistota na trhu IT
Děkuji za pozornost
►Rudolf Pecinovský
http://vyuka.pecinovsky.cz/vse
mail: [email protected]
ICQ: 158 156 600
Vaše jistota na trhu IT
Výjimky
Rudolf Pecinovský
[email protected]
Vaše jistota na trhu IT
Obsah s odkazy
►Výjimky
►Výjimky kontrolované a nekontrolované
►Definice vlastních výjimek
Vaše jistota na trhu IT
Výjimky
►Výjimečné situace v programech
►Ošetření nestandardních situací v Javě
►Zpráva o výjimce
►Klíčová slova
►Činnost
►Vyvolání
Výjimečné situace v programech
► V každém programu je alespoň jedna chyba –
program na ni musí být připraven
► Starší programy
● Program vypsal chybové hlášení a ukončil činnost;
● V některých situacích (válcovací stolice, autopilot, …) nepřijatelné
● Funkce vrátí hodnotu signalizující chybu
● Programátor musí neustále testovat, co funkce vrací
● Knihovna měla pro tyto účely vyhrazenu speciální proměnnou,
do níž se v případě chyby zapsal její kód; nahlédnutím do proměnné
program zjistil kód poslední chyby
● Programátor musí neustále testovat, jaká je v proměnné hodnota
► Některé jazyky (Cobol, PL/1, …) proto přišly s koncepcí
ošetření nestandardních situací
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
4
Ošetření nestandardních situací v Javě
► Výjimečná událost =
problém, který brání dalšímu vykonávání části kódu
► Událost je výjimečná v tom, že na rozdíl od běžných problémů
nemá program k vyřešení situace dost informaci
► Program může při výskytu výjimečné události vyvolat výjimku
► Výjimka (exception)
objekt určený k přenosu informací o nastalém problému
z místa jeho vzniku do místa, kde bude problém řešen
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
5
Postup při vyvolání výjimky
1. Vytvoří se výjimka = objekt typu Throwable
(prakticky vždy instance některého z potomků)
2. Vytvořená výjimka se vyhodí =
přeruší se běh programu v místě, kde výjimka vznikla,
a začne se hledat místo, kde bude daná výjimka ošetřena
3. Ošetření výjimky (handler) by mělo uvést program do stavu,
v němž může jeho vykonávání pokračovat
► Výjimka „probublává“ programem z místa vyhození stále výše
a nenarazí-li cestou nikde na své ošetření,
zachytí ji virtuální stroj, který na standardní chybový výstup
vypíše zprávu o vzniku výjimky
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
6
Systémová zpráva o vzniku výjimky
Zpráva o vzniku výjimky spolu s názvem vlákna,
v němž k výjimce došlo (zde AWT-EventQueue-0)
Popis druhu výjimky (aritmetická výjimka dělení nulou)
Informace o místě, odkud byla volána metoda,
která vyvolala metodu, v níž došlo k vyhození výjimky
Informace o místě, odkud byla volána metoda,
v níž došlo k vyhození výjimky
Úplný název třídy včetně balíčku
Copyright © 2006, Rudolf Pecinovský
Název metody
VŠE – 05
Název souboru se
zdrojovým kódem
Číslo řádku zdrojáku,
kde došlo k výjimce
7
Klíčová slova související s výjimkami
► try (zkus)
Označuje blok kódu, v němž může dojít k výjimce
► throw (hoď)
Příkaz k vyhození výjimky;
musí být následován odkazem na existující instanci
► catch (chyť)
Blok ošetřující výjimku, která je zadána jako parametr
► finally (na konec)
Blok s povinnými závěrečnými akcemi nezávisejícími
na případném vzniku výjimky
► throws (hází)
Uvození seznamu výjimek vyhazovaných danou metodou
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
8
Vyvolání a ošetření výjimky v kódu
try {
//Kód, který může vyvolat výjimky
}
catch( Typ1 id1 ) {
//Ošetření výjimek typu Typ1
}
...
catch( TypN idN ) {
//ošetření výjimek typu TypN
}
finally {
//Kód, který se na závěr VŽDY provede
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
9
Náznak činnosti – řádný průběh
nedojde k vyvolání výjimky
= nedojde k chybě
try {
příkaz1();
příkaz2();
příkaz3();
}
catch ( xxxException e ) {
příkazProOšetřeníChyby();
}
Bloky catch
catch (…..
se přeskočí
finally {
ukončovacíPříkazy();
}
dalšíPříkaz();
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
12
Náznak činnosti – ošetřený výjimka
try {
příkaz1(); Při provádění metody příkaz2
dojde k ošetřené chybě
příkaz2();
příkaz3();
Byla vyhozena výjimka
tohoto typu nebo typu
}
některého z potomků
catch ( xxxException e ) {
příkazProOšetřeníChyby();
}
Ostatní bloky catch
catch (…..
se přeskočí
finally {
ukončovacíPříkazy();
}
dalšíPříkaz();
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
13
Náznak činnosti – neošetřená výjimka
Při provádění metody příkaz2
dojde k NEošetřené chybě
try {
příkaz1();
příkaz2();
příkaz3();
}
catch ( xxxException e ) {
příkazProOšetřeníChyby();
}
Ošetření nebylo nalezeno =>
catch (…..
provede se blok finally
a opouští se metoda
finally {
ukončovacíPříkazy();
}
dalšíPříkaz();
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
14
Vyvolání výjimky
public class Xyz implements Comparable
{
public bolean compareTo( Object o )
{
if( !(o instanceOf Xyz) )
throw new ClassCastException (
"\nPokus o porovnání s neporovnatelnou"
+ " instancí " + o );
//Zjištění, kdo je větší
return vysledek;
}
}
► Instanci nemusíme vytvářet až v příkazu throw,
můžeme ji vytvořit kdykoliv před tím a pak mu ji jen předat
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
15
Vaše jistota na trhu IT
Výjimky kontrolované a
nekontrolované
►Hierarchie výjimek
►Pořadí výjimek v blocích catch
►Metody generující výjimky
►Metody třídy Throwable
►Zřetězené výjimky
►Převod kontrolovaných na nekontrolované
Charakteristika
► Výjimky, které jsou potomky třídy RuntimeException
nebo Error označujeme jako nekontrolované (unchecked),
protože překladač nekontroluje, zda je na ně program připraven
► Ostatní výjimky označujeme jako kontrolované (checked),
protože překladač kontroluje dodržení pravidel:
● Každá metoda, která může vyhodit kontrolovanou výjimku,
se musí k této skutečnosti veřejně přihlásit
● Každé použití metody, která může vyhodit kontrolovanou výjimku,
musí být buď uzavřeno v bloku try…catch,
nebo se volající metoda musí přihlásit k tomu,
že může také vyhodit danou kontrolovanou výjimku
► Nekontrolované výjimky ohlašují chyby v programu,
kontrolované výjimky očekávatelné situace,
na jejichž výskyt má být program připraven
a měl by na ně umět reagovat
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
17
Hierarchie výjimek
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
18
Pořadí výjimek v blocích catch
► Třída NumberFormatException
je potomkem třídy RuntimeException
try {
Syntaktická chyba,
......
na druhý blok catch nikdy nedojde
}
catch (RuntimeException e) {
.........
}
Obrácené pořadí bloků catch
catch (NumberFormatException e){
vše vyřeší
........
try {
}
......
}
catch (NumberFormatException e) {
.........
}
catch (RuntimeException e){
........
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
19
Metody generující výjimky
► Java vyžaduje, aby programy, které používají metody
schopné vyvolat kontrolované výjimky,
byly o této schopnosti používaných metod informovány =>
pak vědí, které výjimku musí umět zachytit a ošetřit
► Všechny kontrolované výjimky, které může metoda vyhodit,
musí deklarovat v hlavičce za klíčovým slovem throws
► Deklarace vyhazování nekontrolovaných výjimek není povinná
public void metoda()
throws KontrolovanáVýjimka1,
KontrolovanáVýjimka2
{
// Tělo metody
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
20
Metody třídy Throwable
► String getMessage()
Vrátí zprávu popisující danou výjimku
► String toString()
Vrátí název třídy výjimky následovaný případnou zprávou
► void printStackTrace()
Vytiskne toString() následovaný sadou informací o volající
posloupnosti, která vedla k vzniku výjimky
► Throwable fillInStackTrace()
Připraví nové informace o volací posloupnosti
vedoucí k místu zavolání této metody
► StackTraceElement[] getStackTrace()
Vrátí uchované informace o volací posloupnosti dané výjimky
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
21
Zřetězené výjimky
► V některých situacích je vhodné v rámci ošetření výjimky vyvolat
jinou výjimku, a přitom umožnit zjistit,
která výjimka byla prvotním hybatelem celé akce
► Řada výjimek má mezi svými konstruktory i takové,
které akceptují jako poslední parametr
odkaz na výjimku, jež byla příčinou vyvolání dané výjimky
► Chce-li se program zeptat výjimky na výjimku, která ji způsobila,
použije metodu
public Throwable getCause()
► Ve zprávě o vyvolání výjimky jsou místa, kde byla jedna výjimka
nahrazena jinou, označována textem caused by:
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
22
Ukázka výpisu při zřetězení výjimek
HighLevelException: MidLevelException: LowLevelException
at Junk.a(Junk.java:13)
at Junk.main(Junk.java:4)
Caused by: MidLevelException: LowLevelException
at Junk.c(Junk.java:23)
at Junk.b(Junk.java:17)
at Junk.a(Junk.java:11)
... 1 more
Caused by: LowLevelException
at Junk.e(Junk.java:30)
at Junk.d(Junk.java:27)
at Junk.c(Junk.java:21)
... 3 more
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
23
Převod kontrolovaných na nekontrolované
► Ošetřování kontrolovaných výjimek obtěžuje
► Víme-li, že k dané výjimce nejspíš nedojde
a ošetřujeme-li ji pouze proto, že na tom překladač trvá,
můžeme pro případ, že by k výjimce přece jenom došlo
zaměnit kontrolovanou výjimku za nekontrolovanou
public void prevod( String s ) {
try {
prověř( s );
} catch( Exception ex ) {
throw new RuntimeException( " Neprověřeno! ", ex );
}
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
24
Vaše jistota na trhu IT
Definice vlastních výjimek
►Hierarchie výjimek
►Pořadí výjimek v blocích catch
►Metody generující výjimky
►Metody třídy Throwable
►Vlastní výjimky
►Zásady správného používání výjimek
Definice vlastních výjimek
► Výjimky jsou zcela běžné třídy;
považujeme-li to proto za vhodné, můžeme definovat i vlastní
► Před definicí nové výjimky bychom si měli ujasnit,
bude-li kontrolovaná či nekontrolovaná;
podle toho definujeme jejího předka
► Název výjimek končí dle konvencí slovem Exception
před nímž je naznačena podstata dané výjimky
● IllegalArgumetnException
● NoSuchMethodException
● BadStringOperationException
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
26
Příklad vlastní kontrolované výjimky
public class VelkýPrůšvihException
extends Exception
{
public VelkýPrůšvihException() {};
public VelkýPrůšvihException( String zpráva ) {
super( zpráva );
}
public VelkýPrůšvihException(String zpráva,
Throwable původce ) {
super( zpráva, původce );
}
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
27
Test správného vyhození výjimky
► Na vytvářených programech je třeba otestovat i to,
že v definovaných situacích vyhodí požadovanou výjimku
public void testVyhozeníVýjimky()
{
try {
metodaKteráMáVyhoditVýjimku();
} catch ( VelkýPrůšvihException vpe ) {
return;
}
fail( "Nebyla vyhozena výjimka VelkýPrůšvihException" );
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
28
Zásady správného používání výjimek
1/2
Neignorujte
výjimky
try {
//Nějaký kód
}
catch(Exception e){}
► Výjimky, o nichž víte, že nemohou nastat,
převeďte na nekontrolované pro případ,
že by v budoucích verzích programu nastat mohly
► Při ošetřování výjimek, které nastat mohou,
ale nemají vliv na chod programu,
vložte do těla ošetření alespoň vysvětlující komentář
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
29
Zásady správného používání výjimek
2/2
► Používejte výjimky pouze k ošetření výjimečných stavů
► Kontrolované výjimky používejte u stavů, z nichž se lze zotavit,
jinak použijte výjimky nekontrolované
► Vyhýbejte se zbytečnému používání kontrolovaných výjimek
● Programátory ošetřování kontrolovaných výjimek obtěžuje
a mají pak tendenci je ošetřovat prázdným blokem catch
► Dávejte přednost standardním výjimkám,
vyvolávejte výjimky odpovídající dané abstrakci
● Programátoři by měli z názvu výjimky poznat, co se stalo
● Standardní výjimky mají všeobecně známý význam
► Snažte se o atomičnost selhání; i po vyhození výjimky
by měl být objekt v dobře definovaném stavu
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
30
Zásady správného používání výjimek
3/2
► Doplňujte výjimky zprávami,
výjimka by sama měla poskytnout dostatek informací
a neměla by programátora nutit k podrobnější analýze programu
► Dokumentujte vyvolávané výjimky v dokumentačních
komentářích pomocí značky @throws
► Nedělejte bloky try zbytečně velké,
kód uvnitř těchto bloků se neoptimalizuje
► Umíte-li výjimku v metodě ošetřit, udělejte to
► Detekuje-li se chyba v jedné metodě a má se ošetřit v jiné
(stejné či jiné instance), použijte výjimku.
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
31
Nejčastěji používané výjimky
1/2
► IllegalArgumentException
Byla zadána nepovolená hodnota parametru
● Např. chci nastavit zápornou velikost grafického tvaru
► IllegalStateException
V daném stavu objektu nelze metodu provést
● Např. otevřu soubor, přečtu pár vět, zavřu soubor a chci znovu přečíst větu
► NullPointerException
Byla vyvolána metoda instance, na níž ukazuje prázdný odkaz,
nebo byl předán nepovolený prázdný odkaz v parametru
► ArrayIndexOutOfBoundException
Byly zadány špatné meze pole, buď záporné nebo moc velké
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
32
Nejčastěji používané výjimky
2/2
► ConcurrentModificationException
V průběhu iterace byla změněna struktura kontejneru
● Např. byl do kontejneru přidán prvek
► NumberFormatException
Je požadován špatný převod řetězce na číslo či naopak
● Chci-li např. převést na číslo řetězec, který není číslem
● Častá chyba v metodách String.format či PrintStream.printf
► ClassCastException
Požadované přetypování není možné
► UnsupportedOperationException
Požadovaná operace není podporována
(např. chci přidat prvek do neměnného kontejneru)
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
33
Vaše jistota na trhu IT
Děkuji za pozornost
►Rudolf Pecinovský
http://vyuka.pecinovsky.cz/vse
mail: [email protected]
ICQ: 158 156 600
Slide 2
Vaše jistota na trhu IT
Výjimky
Rudolf Pecinovský
[email protected]
Vaše jistota na trhu IT
Obsah s odkazy
►Výjimky
►Výjimky kontrolované a nekontrolované
►Definice vlastních výjimek
Vaše jistota na trhu IT
Výjimky
►Výjimečné situace v programech
►Ošetření nestandardních situací v Javě
►Zpráva o výjimce
►Klíčová slova
►Činnost
►Vyvolání
Výjimečné situace v programech
► V každém programu je alespoň jedna chyba –
program na ni musí být připraven
► Starší programy
● Program vypsal chybové hlášení a ukončil činnost;
● V některých situacích (válcovací stolice, autopilot, …) nepřijatelné
● Funkce vrátí hodnotu signalizující chybu
● Programátor musí neustále testovat, co funkce vrací
● Knihovna měla pro tyto účely vyhrazenu speciální proměnnou,
do níž se v případě chyby zapsal její kód; nahlédnutím do proměnné
program zjistil kód poslední chyby
● Programátor musí neustále testovat, jaká je v proměnné hodnota
► Některé jazyky (Cobol, PL/1, …) proto přišly s koncepcí
ošetření nestandardních situací
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
4
Ošetření nestandardních situací v Javě
► Výjimečná událost =
problém, který brání dalšímu vykonávání části kódu
► Událost je výjimečná v tom, že na rozdíl od běžných problémů
nemá program k vyřešení situace dost informaci
► Program může při výskytu výjimečné události vyvolat výjimku
► Výjimka (exception)
objekt určený k přenosu informací o nastalém problému
z místa jeho vzniku do místa, kde bude problém řešen
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
5
Postup při vyvolání výjimky
1. Vytvoří se výjimka = objekt typu Throwable
(prakticky vždy instance některého z potomků)
2. Vytvořená výjimka se vyhodí =
přeruší se běh programu v místě, kde výjimka vznikla,
a začne se hledat místo, kde bude daná výjimka ošetřena
3. Ošetření výjimky (handler) by mělo uvést program do stavu,
v němž může jeho vykonávání pokračovat
► Výjimka „probublává“ programem z místa vyhození stále výše
a nenarazí-li cestou nikde na své ošetření,
zachytí ji virtuální stroj, který na standardní chybový výstup
vypíše zprávu o vzniku výjimky
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
6
Systémová zpráva o vzniku výjimky
Zpráva o vzniku výjimky spolu s názvem vlákna,
v němž k výjimce došlo (zde AWT-EventQueue-0)
Popis druhu výjimky (aritmetická výjimka dělení nulou)
Informace o místě, odkud byla volána metoda,
která vyvolala metodu, v níž došlo k vyhození výjimky
Informace o místě, odkud byla volána metoda,
v níž došlo k vyhození výjimky
Úplný název třídy včetně balíčku
Copyright © 2006, Rudolf Pecinovský
Název metody
VŠE – 05
Název souboru se
zdrojovým kódem
Číslo řádku zdrojáku,
kde došlo k výjimce
7
Klíčová slova související s výjimkami
► try (zkus)
Označuje blok kódu, v němž může dojít k výjimce
► throw (hoď)
Příkaz k vyhození výjimky;
musí být následován odkazem na existující instanci
► catch (chyť)
Blok ošetřující výjimku, která je zadána jako parametr
► finally (na konec)
Blok s povinnými závěrečnými akcemi nezávisejícími
na případném vzniku výjimky
► throws (hází)
Uvození seznamu výjimek vyhazovaných danou metodou
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
8
Vyvolání a ošetření výjimky v kódu
try {
//Kód, který může vyvolat výjimky
}
catch( Typ1 id1 ) {
//Ošetření výjimek typu Typ1
}
...
catch( TypN idN ) {
//ošetření výjimek typu TypN
}
finally {
//Kód, který se na závěr VŽDY provede
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
9
Náznak činnosti – řádný průběh
nedojde k vyvolání výjimky
= nedojde k chybě
try {
příkaz1();
příkaz2();
příkaz3();
}
catch ( xxxException e ) {
příkazProOšetřeníChyby();
}
Bloky catch
catch (…..
se přeskočí
finally {
ukončovacíPříkazy();
}
dalšíPříkaz();
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
12
Náznak činnosti – ošetřený výjimka
try {
příkaz1(); Při provádění metody příkaz2
dojde k ošetřené chybě
příkaz2();
příkaz3();
Byla vyhozena výjimka
tohoto typu nebo typu
}
některého z potomků
catch ( xxxException e ) {
příkazProOšetřeníChyby();
}
Ostatní bloky catch
catch (…..
se přeskočí
finally {
ukončovacíPříkazy();
}
dalšíPříkaz();
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
13
Náznak činnosti – neošetřená výjimka
Při provádění metody příkaz2
dojde k NEošetřené chybě
try {
příkaz1();
příkaz2();
příkaz3();
}
catch ( xxxException e ) {
příkazProOšetřeníChyby();
}
Ošetření nebylo nalezeno =>
catch (…..
provede se blok finally
a opouští se metoda
finally {
ukončovacíPříkazy();
}
dalšíPříkaz();
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
14
Vyvolání výjimky
public class Xyz implements Comparable
{
public bolean compareTo( Object o )
{
if( !(o instanceOf Xyz) )
throw new ClassCastException (
"\nPokus o porovnání s neporovnatelnou"
+ " instancí " + o );
//Zjištění, kdo je větší
return vysledek;
}
}
► Instanci nemusíme vytvářet až v příkazu throw,
můžeme ji vytvořit kdykoliv před tím a pak mu ji jen předat
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
15
Vaše jistota na trhu IT
Výjimky kontrolované a
nekontrolované
►Hierarchie výjimek
►Pořadí výjimek v blocích catch
►Metody generující výjimky
►Metody třídy Throwable
►Zřetězené výjimky
►Převod kontrolovaných na nekontrolované
Charakteristika
► Výjimky, které jsou potomky třídy RuntimeException
nebo Error označujeme jako nekontrolované (unchecked),
protože překladač nekontroluje, zda je na ně program připraven
► Ostatní výjimky označujeme jako kontrolované (checked),
protože překladač kontroluje dodržení pravidel:
● Každá metoda, která může vyhodit kontrolovanou výjimku,
se musí k této skutečnosti veřejně přihlásit
● Každé použití metody, která může vyhodit kontrolovanou výjimku,
musí být buď uzavřeno v bloku try…catch,
nebo se volající metoda musí přihlásit k tomu,
že může také vyhodit danou kontrolovanou výjimku
► Nekontrolované výjimky ohlašují chyby v programu,
kontrolované výjimky očekávatelné situace,
na jejichž výskyt má být program připraven
a měl by na ně umět reagovat
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
17
Hierarchie výjimek
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
18
Pořadí výjimek v blocích catch
► Třída NumberFormatException
je potomkem třídy RuntimeException
try {
Syntaktická chyba,
......
na druhý blok catch nikdy nedojde
}
catch (RuntimeException e) {
.........
}
Obrácené pořadí bloků catch
catch (NumberFormatException e){
vše vyřeší
........
try {
}
......
}
catch (NumberFormatException e) {
.........
}
catch (RuntimeException e){
........
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
19
Metody generující výjimky
► Java vyžaduje, aby programy, které používají metody
schopné vyvolat kontrolované výjimky,
byly o této schopnosti používaných metod informovány =>
pak vědí, které výjimku musí umět zachytit a ošetřit
► Všechny kontrolované výjimky, které může metoda vyhodit,
musí deklarovat v hlavičce za klíčovým slovem throws
► Deklarace vyhazování nekontrolovaných výjimek není povinná
public void metoda()
throws KontrolovanáVýjimka1,
KontrolovanáVýjimka2
{
// Tělo metody
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
20
Metody třídy Throwable
► String getMessage()
Vrátí zprávu popisující danou výjimku
► String toString()
Vrátí název třídy výjimky následovaný případnou zprávou
► void printStackTrace()
Vytiskne toString() následovaný sadou informací o volající
posloupnosti, která vedla k vzniku výjimky
► Throwable fillInStackTrace()
Připraví nové informace o volací posloupnosti
vedoucí k místu zavolání této metody
► StackTraceElement[] getStackTrace()
Vrátí uchované informace o volací posloupnosti dané výjimky
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
21
Zřetězené výjimky
► V některých situacích je vhodné v rámci ošetření výjimky vyvolat
jinou výjimku, a přitom umožnit zjistit,
která výjimka byla prvotním hybatelem celé akce
► Řada výjimek má mezi svými konstruktory i takové,
které akceptují jako poslední parametr
odkaz na výjimku, jež byla příčinou vyvolání dané výjimky
► Chce-li se program zeptat výjimky na výjimku, která ji způsobila,
použije metodu
public Throwable getCause()
► Ve zprávě o vyvolání výjimky jsou místa, kde byla jedna výjimka
nahrazena jinou, označována textem caused by:
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
22
Ukázka výpisu při zřetězení výjimek
HighLevelException: MidLevelException: LowLevelException
at Junk.a(Junk.java:13)
at Junk.main(Junk.java:4)
Caused by: MidLevelException: LowLevelException
at Junk.c(Junk.java:23)
at Junk.b(Junk.java:17)
at Junk.a(Junk.java:11)
... 1 more
Caused by: LowLevelException
at Junk.e(Junk.java:30)
at Junk.d(Junk.java:27)
at Junk.c(Junk.java:21)
... 3 more
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
23
Převod kontrolovaných na nekontrolované
► Ošetřování kontrolovaných výjimek obtěžuje
► Víme-li, že k dané výjimce nejspíš nedojde
a ošetřujeme-li ji pouze proto, že na tom překladač trvá,
můžeme pro případ, že by k výjimce přece jenom došlo
zaměnit kontrolovanou výjimku za nekontrolovanou
public void prevod( String s ) {
try {
prověř( s );
} catch( Exception ex ) {
throw new RuntimeException( " Neprověřeno! ", ex );
}
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
24
Vaše jistota na trhu IT
Definice vlastních výjimek
►Hierarchie výjimek
►Pořadí výjimek v blocích catch
►Metody generující výjimky
►Metody třídy Throwable
►Vlastní výjimky
►Zásady správného používání výjimek
Definice vlastních výjimek
► Výjimky jsou zcela běžné třídy;
považujeme-li to proto za vhodné, můžeme definovat i vlastní
► Před definicí nové výjimky bychom si měli ujasnit,
bude-li kontrolovaná či nekontrolovaná;
podle toho definujeme jejího předka
► Název výjimek končí dle konvencí slovem Exception
před nímž je naznačena podstata dané výjimky
● IllegalArgumetnException
● NoSuchMethodException
● BadStringOperationException
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
26
Příklad vlastní kontrolované výjimky
public class VelkýPrůšvihException
extends Exception
{
public VelkýPrůšvihException() {};
public VelkýPrůšvihException( String zpráva ) {
super( zpráva );
}
public VelkýPrůšvihException(String zpráva,
Throwable původce ) {
super( zpráva, původce );
}
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
27
Test správného vyhození výjimky
► Na vytvářených programech je třeba otestovat i to,
že v definovaných situacích vyhodí požadovanou výjimku
public void testVyhozeníVýjimky()
{
try {
metodaKteráMáVyhoditVýjimku();
} catch ( VelkýPrůšvihException vpe ) {
return;
}
fail( "Nebyla vyhozena výjimka VelkýPrůšvihException" );
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
28
Zásady správného používání výjimek
1/2
Neignorujte
výjimky
try {
//Nějaký kód
}
catch(Exception e){}
► Výjimky, o nichž víte, že nemohou nastat,
převeďte na nekontrolované pro případ,
že by v budoucích verzích programu nastat mohly
► Při ošetřování výjimek, které nastat mohou,
ale nemají vliv na chod programu,
vložte do těla ošetření alespoň vysvětlující komentář
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
29
Zásady správného používání výjimek
2/2
► Používejte výjimky pouze k ošetření výjimečných stavů
► Kontrolované výjimky používejte u stavů, z nichž se lze zotavit,
jinak použijte výjimky nekontrolované
► Vyhýbejte se zbytečnému používání kontrolovaných výjimek
● Programátory ošetřování kontrolovaných výjimek obtěžuje
a mají pak tendenci je ošetřovat prázdným blokem catch
► Dávejte přednost standardním výjimkám,
vyvolávejte výjimky odpovídající dané abstrakci
● Programátoři by měli z názvu výjimky poznat, co se stalo
● Standardní výjimky mají všeobecně známý význam
► Snažte se o atomičnost selhání; i po vyhození výjimky
by měl být objekt v dobře definovaném stavu
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
30
Zásady správného používání výjimek
3/2
► Doplňujte výjimky zprávami,
výjimka by sama měla poskytnout dostatek informací
a neměla by programátora nutit k podrobnější analýze programu
► Dokumentujte vyvolávané výjimky v dokumentačních
komentářích pomocí značky @throws
► Nedělejte bloky try zbytečně velké,
kód uvnitř těchto bloků se neoptimalizuje
► Umíte-li výjimku v metodě ošetřit, udělejte to
► Detekuje-li se chyba v jedné metodě a má se ošetřit v jiné
(stejné či jiné instance), použijte výjimku.
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
31
Nejčastěji používané výjimky
1/2
► IllegalArgumentException
Byla zadána nepovolená hodnota parametru
● Např. chci nastavit zápornou velikost grafického tvaru
► IllegalStateException
V daném stavu objektu nelze metodu provést
● Např. otevřu soubor, přečtu pár vět, zavřu soubor a chci znovu přečíst větu
► NullPointerException
Byla vyvolána metoda instance, na níž ukazuje prázdný odkaz,
nebo byl předán nepovolený prázdný odkaz v parametru
► ArrayIndexOutOfBoundException
Byly zadány špatné meze pole, buď záporné nebo moc velké
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
32
Nejčastěji používané výjimky
2/2
► ConcurrentModificationException
V průběhu iterace byla změněna struktura kontejneru
● Např. byl do kontejneru přidán prvek
► NumberFormatException
Je požadován špatný převod řetězce na číslo či naopak
● Chci-li např. převést na číslo řetězec, který není číslem
● Častá chyba v metodách String.format či PrintStream.printf
► ClassCastException
Požadované přetypování není možné
► UnsupportedOperationException
Požadovaná operace není podporována
(např. chci přidat prvek do neměnného kontejneru)
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
33
Vaše jistota na trhu IT
Děkuji za pozornost
►Rudolf Pecinovský
http://vyuka.pecinovsky.cz/vse
mail: [email protected]
ICQ: 158 156 600
Slide 3
Vaše jistota na trhu IT
Výjimky
Rudolf Pecinovský
[email protected]
Vaše jistota na trhu IT
Obsah s odkazy
►Výjimky
►Výjimky kontrolované a nekontrolované
►Definice vlastních výjimek
Vaše jistota na trhu IT
Výjimky
►Výjimečné situace v programech
►Ošetření nestandardních situací v Javě
►Zpráva o výjimce
►Klíčová slova
►Činnost
►Vyvolání
Výjimečné situace v programech
► V každém programu je alespoň jedna chyba –
program na ni musí být připraven
► Starší programy
● Program vypsal chybové hlášení a ukončil činnost;
● V některých situacích (válcovací stolice, autopilot, …) nepřijatelné
● Funkce vrátí hodnotu signalizující chybu
● Programátor musí neustále testovat, co funkce vrací
● Knihovna měla pro tyto účely vyhrazenu speciální proměnnou,
do níž se v případě chyby zapsal její kód; nahlédnutím do proměnné
program zjistil kód poslední chyby
● Programátor musí neustále testovat, jaká je v proměnné hodnota
► Některé jazyky (Cobol, PL/1, …) proto přišly s koncepcí
ošetření nestandardních situací
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
4
Ošetření nestandardních situací v Javě
► Výjimečná událost =
problém, který brání dalšímu vykonávání části kódu
► Událost je výjimečná v tom, že na rozdíl od běžných problémů
nemá program k vyřešení situace dost informaci
► Program může při výskytu výjimečné události vyvolat výjimku
► Výjimka (exception)
objekt určený k přenosu informací o nastalém problému
z místa jeho vzniku do místa, kde bude problém řešen
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
5
Postup při vyvolání výjimky
1. Vytvoří se výjimka = objekt typu Throwable
(prakticky vždy instance některého z potomků)
2. Vytvořená výjimka se vyhodí =
přeruší se běh programu v místě, kde výjimka vznikla,
a začne se hledat místo, kde bude daná výjimka ošetřena
3. Ošetření výjimky (handler) by mělo uvést program do stavu,
v němž může jeho vykonávání pokračovat
► Výjimka „probublává“ programem z místa vyhození stále výše
a nenarazí-li cestou nikde na své ošetření,
zachytí ji virtuální stroj, který na standardní chybový výstup
vypíše zprávu o vzniku výjimky
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
6
Systémová zpráva o vzniku výjimky
Zpráva o vzniku výjimky spolu s názvem vlákna,
v němž k výjimce došlo (zde AWT-EventQueue-0)
Popis druhu výjimky (aritmetická výjimka dělení nulou)
Informace o místě, odkud byla volána metoda,
která vyvolala metodu, v níž došlo k vyhození výjimky
Informace o místě, odkud byla volána metoda,
v níž došlo k vyhození výjimky
Úplný název třídy včetně balíčku
Copyright © 2006, Rudolf Pecinovský
Název metody
VŠE – 05
Název souboru se
zdrojovým kódem
Číslo řádku zdrojáku,
kde došlo k výjimce
7
Klíčová slova související s výjimkami
► try (zkus)
Označuje blok kódu, v němž může dojít k výjimce
► throw (hoď)
Příkaz k vyhození výjimky;
musí být následován odkazem na existující instanci
► catch (chyť)
Blok ošetřující výjimku, která je zadána jako parametr
► finally (na konec)
Blok s povinnými závěrečnými akcemi nezávisejícími
na případném vzniku výjimky
► throws (hází)
Uvození seznamu výjimek vyhazovaných danou metodou
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
8
Vyvolání a ošetření výjimky v kódu
try {
//Kód, který může vyvolat výjimky
}
catch( Typ1 id1 ) {
//Ošetření výjimek typu Typ1
}
...
catch( TypN idN ) {
//ošetření výjimek typu TypN
}
finally {
//Kód, který se na závěr VŽDY provede
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
9
Náznak činnosti – řádný průběh
nedojde k vyvolání výjimky
= nedojde k chybě
try {
příkaz1();
příkaz2();
příkaz3();
}
catch ( xxxException e ) {
příkazProOšetřeníChyby();
}
Bloky catch
catch (…..
se přeskočí
finally {
ukončovacíPříkazy();
}
dalšíPříkaz();
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
12
Náznak činnosti – ošetřený výjimka
try {
příkaz1(); Při provádění metody příkaz2
dojde k ošetřené chybě
příkaz2();
příkaz3();
Byla vyhozena výjimka
tohoto typu nebo typu
}
některého z potomků
catch ( xxxException e ) {
příkazProOšetřeníChyby();
}
Ostatní bloky catch
catch (…..
se přeskočí
finally {
ukončovacíPříkazy();
}
dalšíPříkaz();
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
13
Náznak činnosti – neošetřená výjimka
Při provádění metody příkaz2
dojde k NEošetřené chybě
try {
příkaz1();
příkaz2();
příkaz3();
}
catch ( xxxException e ) {
příkazProOšetřeníChyby();
}
Ošetření nebylo nalezeno =>
catch (…..
provede se blok finally
a opouští se metoda
finally {
ukončovacíPříkazy();
}
dalšíPříkaz();
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
14
Vyvolání výjimky
public class Xyz implements Comparable
{
public bolean compareTo( Object o )
{
if( !(o instanceOf Xyz) )
throw new ClassCastException (
"\nPokus o porovnání s neporovnatelnou"
+ " instancí " + o );
//Zjištění, kdo je větší
return vysledek;
}
}
► Instanci nemusíme vytvářet až v příkazu throw,
můžeme ji vytvořit kdykoliv před tím a pak mu ji jen předat
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
15
Vaše jistota na trhu IT
Výjimky kontrolované a
nekontrolované
►Hierarchie výjimek
►Pořadí výjimek v blocích catch
►Metody generující výjimky
►Metody třídy Throwable
►Zřetězené výjimky
►Převod kontrolovaných na nekontrolované
Charakteristika
► Výjimky, které jsou potomky třídy RuntimeException
nebo Error označujeme jako nekontrolované (unchecked),
protože překladač nekontroluje, zda je na ně program připraven
► Ostatní výjimky označujeme jako kontrolované (checked),
protože překladač kontroluje dodržení pravidel:
● Každá metoda, která může vyhodit kontrolovanou výjimku,
se musí k této skutečnosti veřejně přihlásit
● Každé použití metody, která může vyhodit kontrolovanou výjimku,
musí být buď uzavřeno v bloku try…catch,
nebo se volající metoda musí přihlásit k tomu,
že může také vyhodit danou kontrolovanou výjimku
► Nekontrolované výjimky ohlašují chyby v programu,
kontrolované výjimky očekávatelné situace,
na jejichž výskyt má být program připraven
a měl by na ně umět reagovat
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
17
Hierarchie výjimek
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
18
Pořadí výjimek v blocích catch
► Třída NumberFormatException
je potomkem třídy RuntimeException
try {
Syntaktická chyba,
......
na druhý blok catch nikdy nedojde
}
catch (RuntimeException e) {
.........
}
Obrácené pořadí bloků catch
catch (NumberFormatException e){
vše vyřeší
........
try {
}
......
}
catch (NumberFormatException e) {
.........
}
catch (RuntimeException e){
........
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
19
Metody generující výjimky
► Java vyžaduje, aby programy, které používají metody
schopné vyvolat kontrolované výjimky,
byly o této schopnosti používaných metod informovány =>
pak vědí, které výjimku musí umět zachytit a ošetřit
► Všechny kontrolované výjimky, které může metoda vyhodit,
musí deklarovat v hlavičce za klíčovým slovem throws
► Deklarace vyhazování nekontrolovaných výjimek není povinná
public void metoda()
throws KontrolovanáVýjimka1,
KontrolovanáVýjimka2
{
// Tělo metody
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
20
Metody třídy Throwable
► String getMessage()
Vrátí zprávu popisující danou výjimku
► String toString()
Vrátí název třídy výjimky následovaný případnou zprávou
► void printStackTrace()
Vytiskne toString() následovaný sadou informací o volající
posloupnosti, která vedla k vzniku výjimky
► Throwable fillInStackTrace()
Připraví nové informace o volací posloupnosti
vedoucí k místu zavolání této metody
► StackTraceElement[] getStackTrace()
Vrátí uchované informace o volací posloupnosti dané výjimky
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
21
Zřetězené výjimky
► V některých situacích je vhodné v rámci ošetření výjimky vyvolat
jinou výjimku, a přitom umožnit zjistit,
která výjimka byla prvotním hybatelem celé akce
► Řada výjimek má mezi svými konstruktory i takové,
které akceptují jako poslední parametr
odkaz na výjimku, jež byla příčinou vyvolání dané výjimky
► Chce-li se program zeptat výjimky na výjimku, která ji způsobila,
použije metodu
public Throwable getCause()
► Ve zprávě o vyvolání výjimky jsou místa, kde byla jedna výjimka
nahrazena jinou, označována textem caused by:
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
22
Ukázka výpisu při zřetězení výjimek
HighLevelException: MidLevelException: LowLevelException
at Junk.a(Junk.java:13)
at Junk.main(Junk.java:4)
Caused by: MidLevelException: LowLevelException
at Junk.c(Junk.java:23)
at Junk.b(Junk.java:17)
at Junk.a(Junk.java:11)
... 1 more
Caused by: LowLevelException
at Junk.e(Junk.java:30)
at Junk.d(Junk.java:27)
at Junk.c(Junk.java:21)
... 3 more
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
23
Převod kontrolovaných na nekontrolované
► Ošetřování kontrolovaných výjimek obtěžuje
► Víme-li, že k dané výjimce nejspíš nedojde
a ošetřujeme-li ji pouze proto, že na tom překladač trvá,
můžeme pro případ, že by k výjimce přece jenom došlo
zaměnit kontrolovanou výjimku za nekontrolovanou
public void prevod( String s ) {
try {
prověř( s );
} catch( Exception ex ) {
throw new RuntimeException( " Neprověřeno! ", ex );
}
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
24
Vaše jistota na trhu IT
Definice vlastních výjimek
►Hierarchie výjimek
►Pořadí výjimek v blocích catch
►Metody generující výjimky
►Metody třídy Throwable
►Vlastní výjimky
►Zásady správného používání výjimek
Definice vlastních výjimek
► Výjimky jsou zcela běžné třídy;
považujeme-li to proto za vhodné, můžeme definovat i vlastní
► Před definicí nové výjimky bychom si měli ujasnit,
bude-li kontrolovaná či nekontrolovaná;
podle toho definujeme jejího předka
► Název výjimek končí dle konvencí slovem Exception
před nímž je naznačena podstata dané výjimky
● IllegalArgumetnException
● NoSuchMethodException
● BadStringOperationException
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
26
Příklad vlastní kontrolované výjimky
public class VelkýPrůšvihException
extends Exception
{
public VelkýPrůšvihException() {};
public VelkýPrůšvihException( String zpráva ) {
super( zpráva );
}
public VelkýPrůšvihException(String zpráva,
Throwable původce ) {
super( zpráva, původce );
}
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
27
Test správného vyhození výjimky
► Na vytvářených programech je třeba otestovat i to,
že v definovaných situacích vyhodí požadovanou výjimku
public void testVyhozeníVýjimky()
{
try {
metodaKteráMáVyhoditVýjimku();
} catch ( VelkýPrůšvihException vpe ) {
return;
}
fail( "Nebyla vyhozena výjimka VelkýPrůšvihException" );
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
28
Zásady správného používání výjimek
1/2
Neignorujte
výjimky
try {
//Nějaký kód
}
catch(Exception e){}
► Výjimky, o nichž víte, že nemohou nastat,
převeďte na nekontrolované pro případ,
že by v budoucích verzích programu nastat mohly
► Při ošetřování výjimek, které nastat mohou,
ale nemají vliv na chod programu,
vložte do těla ošetření alespoň vysvětlující komentář
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
29
Zásady správného používání výjimek
2/2
► Používejte výjimky pouze k ošetření výjimečných stavů
► Kontrolované výjimky používejte u stavů, z nichž se lze zotavit,
jinak použijte výjimky nekontrolované
► Vyhýbejte se zbytečnému používání kontrolovaných výjimek
● Programátory ošetřování kontrolovaných výjimek obtěžuje
a mají pak tendenci je ošetřovat prázdným blokem catch
► Dávejte přednost standardním výjimkám,
vyvolávejte výjimky odpovídající dané abstrakci
● Programátoři by měli z názvu výjimky poznat, co se stalo
● Standardní výjimky mají všeobecně známý význam
► Snažte se o atomičnost selhání; i po vyhození výjimky
by měl být objekt v dobře definovaném stavu
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
30
Zásady správného používání výjimek
3/2
► Doplňujte výjimky zprávami,
výjimka by sama měla poskytnout dostatek informací
a neměla by programátora nutit k podrobnější analýze programu
► Dokumentujte vyvolávané výjimky v dokumentačních
komentářích pomocí značky @throws
► Nedělejte bloky try zbytečně velké,
kód uvnitř těchto bloků se neoptimalizuje
► Umíte-li výjimku v metodě ošetřit, udělejte to
► Detekuje-li se chyba v jedné metodě a má se ošetřit v jiné
(stejné či jiné instance), použijte výjimku.
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
31
Nejčastěji používané výjimky
1/2
► IllegalArgumentException
Byla zadána nepovolená hodnota parametru
● Např. chci nastavit zápornou velikost grafického tvaru
► IllegalStateException
V daném stavu objektu nelze metodu provést
● Např. otevřu soubor, přečtu pár vět, zavřu soubor a chci znovu přečíst větu
► NullPointerException
Byla vyvolána metoda instance, na níž ukazuje prázdný odkaz,
nebo byl předán nepovolený prázdný odkaz v parametru
► ArrayIndexOutOfBoundException
Byly zadány špatné meze pole, buď záporné nebo moc velké
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
32
Nejčastěji používané výjimky
2/2
► ConcurrentModificationException
V průběhu iterace byla změněna struktura kontejneru
● Např. byl do kontejneru přidán prvek
► NumberFormatException
Je požadován špatný převod řetězce na číslo či naopak
● Chci-li např. převést na číslo řetězec, který není číslem
● Častá chyba v metodách String.format či PrintStream.printf
► ClassCastException
Požadované přetypování není možné
► UnsupportedOperationException
Požadovaná operace není podporována
(např. chci přidat prvek do neměnného kontejneru)
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
33
Vaše jistota na trhu IT
Děkuji za pozornost
►Rudolf Pecinovský
http://vyuka.pecinovsky.cz/vse
mail: [email protected]
ICQ: 158 156 600
Slide 4
Vaše jistota na trhu IT
Výjimky
Rudolf Pecinovský
[email protected]
Vaše jistota na trhu IT
Obsah s odkazy
►Výjimky
►Výjimky kontrolované a nekontrolované
►Definice vlastních výjimek
Vaše jistota na trhu IT
Výjimky
►Výjimečné situace v programech
►Ošetření nestandardních situací v Javě
►Zpráva o výjimce
►Klíčová slova
►Činnost
►Vyvolání
Výjimečné situace v programech
► V každém programu je alespoň jedna chyba –
program na ni musí být připraven
► Starší programy
● Program vypsal chybové hlášení a ukončil činnost;
● V některých situacích (válcovací stolice, autopilot, …) nepřijatelné
● Funkce vrátí hodnotu signalizující chybu
● Programátor musí neustále testovat, co funkce vrací
● Knihovna měla pro tyto účely vyhrazenu speciální proměnnou,
do níž se v případě chyby zapsal její kód; nahlédnutím do proměnné
program zjistil kód poslední chyby
● Programátor musí neustále testovat, jaká je v proměnné hodnota
► Některé jazyky (Cobol, PL/1, …) proto přišly s koncepcí
ošetření nestandardních situací
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
4
Ošetření nestandardních situací v Javě
► Výjimečná událost =
problém, který brání dalšímu vykonávání části kódu
► Událost je výjimečná v tom, že na rozdíl od běžných problémů
nemá program k vyřešení situace dost informaci
► Program může při výskytu výjimečné události vyvolat výjimku
► Výjimka (exception)
objekt určený k přenosu informací o nastalém problému
z místa jeho vzniku do místa, kde bude problém řešen
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
5
Postup při vyvolání výjimky
1. Vytvoří se výjimka = objekt typu Throwable
(prakticky vždy instance některého z potomků)
2. Vytvořená výjimka se vyhodí =
přeruší se běh programu v místě, kde výjimka vznikla,
a začne se hledat místo, kde bude daná výjimka ošetřena
3. Ošetření výjimky (handler) by mělo uvést program do stavu,
v němž může jeho vykonávání pokračovat
► Výjimka „probublává“ programem z místa vyhození stále výše
a nenarazí-li cestou nikde na své ošetření,
zachytí ji virtuální stroj, který na standardní chybový výstup
vypíše zprávu o vzniku výjimky
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
6
Systémová zpráva o vzniku výjimky
Zpráva o vzniku výjimky spolu s názvem vlákna,
v němž k výjimce došlo (zde AWT-EventQueue-0)
Popis druhu výjimky (aritmetická výjimka dělení nulou)
Informace o místě, odkud byla volána metoda,
která vyvolala metodu, v níž došlo k vyhození výjimky
Informace o místě, odkud byla volána metoda,
v níž došlo k vyhození výjimky
Úplný název třídy včetně balíčku
Copyright © 2006, Rudolf Pecinovský
Název metody
VŠE – 05
Název souboru se
zdrojovým kódem
Číslo řádku zdrojáku,
kde došlo k výjimce
7
Klíčová slova související s výjimkami
► try (zkus)
Označuje blok kódu, v němž může dojít k výjimce
► throw (hoď)
Příkaz k vyhození výjimky;
musí být následován odkazem na existující instanci
► catch (chyť)
Blok ošetřující výjimku, která je zadána jako parametr
► finally (na konec)
Blok s povinnými závěrečnými akcemi nezávisejícími
na případném vzniku výjimky
► throws (hází)
Uvození seznamu výjimek vyhazovaných danou metodou
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
8
Vyvolání a ošetření výjimky v kódu
try {
//Kód, který může vyvolat výjimky
}
catch( Typ1 id1 ) {
//Ošetření výjimek typu Typ1
}
...
catch( TypN idN ) {
//ošetření výjimek typu TypN
}
finally {
//Kód, který se na závěr VŽDY provede
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
9
Náznak činnosti – řádný průběh
nedojde k vyvolání výjimky
= nedojde k chybě
try {
příkaz1();
příkaz2();
příkaz3();
}
catch ( xxxException e ) {
příkazProOšetřeníChyby();
}
Bloky catch
catch (…..
se přeskočí
finally {
ukončovacíPříkazy();
}
dalšíPříkaz();
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
12
Náznak činnosti – ošetřený výjimka
try {
příkaz1(); Při provádění metody příkaz2
dojde k ošetřené chybě
příkaz2();
příkaz3();
Byla vyhozena výjimka
tohoto typu nebo typu
}
některého z potomků
catch ( xxxException e ) {
příkazProOšetřeníChyby();
}
Ostatní bloky catch
catch (…..
se přeskočí
finally {
ukončovacíPříkazy();
}
dalšíPříkaz();
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
13
Náznak činnosti – neošetřená výjimka
Při provádění metody příkaz2
dojde k NEošetřené chybě
try {
příkaz1();
příkaz2();
příkaz3();
}
catch ( xxxException e ) {
příkazProOšetřeníChyby();
}
Ošetření nebylo nalezeno =>
catch (…..
provede se blok finally
a opouští se metoda
finally {
ukončovacíPříkazy();
}
dalšíPříkaz();
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
14
Vyvolání výjimky
public class Xyz implements Comparable
{
public bolean compareTo( Object o )
{
if( !(o instanceOf Xyz) )
throw new ClassCastException (
"\nPokus o porovnání s neporovnatelnou"
+ " instancí " + o );
//Zjištění, kdo je větší
return vysledek;
}
}
► Instanci nemusíme vytvářet až v příkazu throw,
můžeme ji vytvořit kdykoliv před tím a pak mu ji jen předat
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
15
Vaše jistota na trhu IT
Výjimky kontrolované a
nekontrolované
►Hierarchie výjimek
►Pořadí výjimek v blocích catch
►Metody generující výjimky
►Metody třídy Throwable
►Zřetězené výjimky
►Převod kontrolovaných na nekontrolované
Charakteristika
► Výjimky, které jsou potomky třídy RuntimeException
nebo Error označujeme jako nekontrolované (unchecked),
protože překladač nekontroluje, zda je na ně program připraven
► Ostatní výjimky označujeme jako kontrolované (checked),
protože překladač kontroluje dodržení pravidel:
● Každá metoda, která může vyhodit kontrolovanou výjimku,
se musí k této skutečnosti veřejně přihlásit
● Každé použití metody, která může vyhodit kontrolovanou výjimku,
musí být buď uzavřeno v bloku try…catch,
nebo se volající metoda musí přihlásit k tomu,
že může také vyhodit danou kontrolovanou výjimku
► Nekontrolované výjimky ohlašují chyby v programu,
kontrolované výjimky očekávatelné situace,
na jejichž výskyt má být program připraven
a měl by na ně umět reagovat
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
17
Hierarchie výjimek
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
18
Pořadí výjimek v blocích catch
► Třída NumberFormatException
je potomkem třídy RuntimeException
try {
Syntaktická chyba,
......
na druhý blok catch nikdy nedojde
}
catch (RuntimeException e) {
.........
}
Obrácené pořadí bloků catch
catch (NumberFormatException e){
vše vyřeší
........
try {
}
......
}
catch (NumberFormatException e) {
.........
}
catch (RuntimeException e){
........
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
19
Metody generující výjimky
► Java vyžaduje, aby programy, které používají metody
schopné vyvolat kontrolované výjimky,
byly o této schopnosti používaných metod informovány =>
pak vědí, které výjimku musí umět zachytit a ošetřit
► Všechny kontrolované výjimky, které může metoda vyhodit,
musí deklarovat v hlavičce za klíčovým slovem throws
► Deklarace vyhazování nekontrolovaných výjimek není povinná
public void metoda()
throws KontrolovanáVýjimka1,
KontrolovanáVýjimka2
{
// Tělo metody
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
20
Metody třídy Throwable
► String getMessage()
Vrátí zprávu popisující danou výjimku
► String toString()
Vrátí název třídy výjimky následovaný případnou zprávou
► void printStackTrace()
Vytiskne toString() následovaný sadou informací o volající
posloupnosti, která vedla k vzniku výjimky
► Throwable fillInStackTrace()
Připraví nové informace o volací posloupnosti
vedoucí k místu zavolání této metody
► StackTraceElement[] getStackTrace()
Vrátí uchované informace o volací posloupnosti dané výjimky
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
21
Zřetězené výjimky
► V některých situacích je vhodné v rámci ošetření výjimky vyvolat
jinou výjimku, a přitom umožnit zjistit,
která výjimka byla prvotním hybatelem celé akce
► Řada výjimek má mezi svými konstruktory i takové,
které akceptují jako poslední parametr
odkaz na výjimku, jež byla příčinou vyvolání dané výjimky
► Chce-li se program zeptat výjimky na výjimku, která ji způsobila,
použije metodu
public Throwable getCause()
► Ve zprávě o vyvolání výjimky jsou místa, kde byla jedna výjimka
nahrazena jinou, označována textem caused by:
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
22
Ukázka výpisu při zřetězení výjimek
HighLevelException: MidLevelException: LowLevelException
at Junk.a(Junk.java:13)
at Junk.main(Junk.java:4)
Caused by: MidLevelException: LowLevelException
at Junk.c(Junk.java:23)
at Junk.b(Junk.java:17)
at Junk.a(Junk.java:11)
... 1 more
Caused by: LowLevelException
at Junk.e(Junk.java:30)
at Junk.d(Junk.java:27)
at Junk.c(Junk.java:21)
... 3 more
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
23
Převod kontrolovaných na nekontrolované
► Ošetřování kontrolovaných výjimek obtěžuje
► Víme-li, že k dané výjimce nejspíš nedojde
a ošetřujeme-li ji pouze proto, že na tom překladač trvá,
můžeme pro případ, že by k výjimce přece jenom došlo
zaměnit kontrolovanou výjimku za nekontrolovanou
public void prevod( String s ) {
try {
prověř( s );
} catch( Exception ex ) {
throw new RuntimeException( " Neprověřeno! ", ex );
}
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
24
Vaše jistota na trhu IT
Definice vlastních výjimek
►Hierarchie výjimek
►Pořadí výjimek v blocích catch
►Metody generující výjimky
►Metody třídy Throwable
►Vlastní výjimky
►Zásady správného používání výjimek
Definice vlastních výjimek
► Výjimky jsou zcela běžné třídy;
považujeme-li to proto za vhodné, můžeme definovat i vlastní
► Před definicí nové výjimky bychom si měli ujasnit,
bude-li kontrolovaná či nekontrolovaná;
podle toho definujeme jejího předka
► Název výjimek končí dle konvencí slovem Exception
před nímž je naznačena podstata dané výjimky
● IllegalArgumetnException
● NoSuchMethodException
● BadStringOperationException
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
26
Příklad vlastní kontrolované výjimky
public class VelkýPrůšvihException
extends Exception
{
public VelkýPrůšvihException() {};
public VelkýPrůšvihException( String zpráva ) {
super( zpráva );
}
public VelkýPrůšvihException(String zpráva,
Throwable původce ) {
super( zpráva, původce );
}
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
27
Test správného vyhození výjimky
► Na vytvářených programech je třeba otestovat i to,
že v definovaných situacích vyhodí požadovanou výjimku
public void testVyhozeníVýjimky()
{
try {
metodaKteráMáVyhoditVýjimku();
} catch ( VelkýPrůšvihException vpe ) {
return;
}
fail( "Nebyla vyhozena výjimka VelkýPrůšvihException" );
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
28
Zásady správného používání výjimek
1/2
Neignorujte
výjimky
try {
//Nějaký kód
}
catch(Exception e){}
► Výjimky, o nichž víte, že nemohou nastat,
převeďte na nekontrolované pro případ,
že by v budoucích verzích programu nastat mohly
► Při ošetřování výjimek, které nastat mohou,
ale nemají vliv na chod programu,
vložte do těla ošetření alespoň vysvětlující komentář
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
29
Zásady správného používání výjimek
2/2
► Používejte výjimky pouze k ošetření výjimečných stavů
► Kontrolované výjimky používejte u stavů, z nichž se lze zotavit,
jinak použijte výjimky nekontrolované
► Vyhýbejte se zbytečnému používání kontrolovaných výjimek
● Programátory ošetřování kontrolovaných výjimek obtěžuje
a mají pak tendenci je ošetřovat prázdným blokem catch
► Dávejte přednost standardním výjimkám,
vyvolávejte výjimky odpovídající dané abstrakci
● Programátoři by měli z názvu výjimky poznat, co se stalo
● Standardní výjimky mají všeobecně známý význam
► Snažte se o atomičnost selhání; i po vyhození výjimky
by měl být objekt v dobře definovaném stavu
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
30
Zásady správného používání výjimek
3/2
► Doplňujte výjimky zprávami,
výjimka by sama měla poskytnout dostatek informací
a neměla by programátora nutit k podrobnější analýze programu
► Dokumentujte vyvolávané výjimky v dokumentačních
komentářích pomocí značky @throws
► Nedělejte bloky try zbytečně velké,
kód uvnitř těchto bloků se neoptimalizuje
► Umíte-li výjimku v metodě ošetřit, udělejte to
► Detekuje-li se chyba v jedné metodě a má se ošetřit v jiné
(stejné či jiné instance), použijte výjimku.
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
31
Nejčastěji používané výjimky
1/2
► IllegalArgumentException
Byla zadána nepovolená hodnota parametru
● Např. chci nastavit zápornou velikost grafického tvaru
► IllegalStateException
V daném stavu objektu nelze metodu provést
● Např. otevřu soubor, přečtu pár vět, zavřu soubor a chci znovu přečíst větu
► NullPointerException
Byla vyvolána metoda instance, na níž ukazuje prázdný odkaz,
nebo byl předán nepovolený prázdný odkaz v parametru
► ArrayIndexOutOfBoundException
Byly zadány špatné meze pole, buď záporné nebo moc velké
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
32
Nejčastěji používané výjimky
2/2
► ConcurrentModificationException
V průběhu iterace byla změněna struktura kontejneru
● Např. byl do kontejneru přidán prvek
► NumberFormatException
Je požadován špatný převod řetězce na číslo či naopak
● Chci-li např. převést na číslo řetězec, který není číslem
● Častá chyba v metodách String.format či PrintStream.printf
► ClassCastException
Požadované přetypování není možné
► UnsupportedOperationException
Požadovaná operace není podporována
(např. chci přidat prvek do neměnného kontejneru)
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
33
Vaše jistota na trhu IT
Děkuji za pozornost
►Rudolf Pecinovský
http://vyuka.pecinovsky.cz/vse
mail: [email protected]
ICQ: 158 156 600
Slide 5
Vaše jistota na trhu IT
Výjimky
Rudolf Pecinovský
[email protected]
Vaše jistota na trhu IT
Obsah s odkazy
►Výjimky
►Výjimky kontrolované a nekontrolované
►Definice vlastních výjimek
Vaše jistota na trhu IT
Výjimky
►Výjimečné situace v programech
►Ošetření nestandardních situací v Javě
►Zpráva o výjimce
►Klíčová slova
►Činnost
►Vyvolání
Výjimečné situace v programech
► V každém programu je alespoň jedna chyba –
program na ni musí být připraven
► Starší programy
● Program vypsal chybové hlášení a ukončil činnost;
● V některých situacích (válcovací stolice, autopilot, …) nepřijatelné
● Funkce vrátí hodnotu signalizující chybu
● Programátor musí neustále testovat, co funkce vrací
● Knihovna měla pro tyto účely vyhrazenu speciální proměnnou,
do níž se v případě chyby zapsal její kód; nahlédnutím do proměnné
program zjistil kód poslední chyby
● Programátor musí neustále testovat, jaká je v proměnné hodnota
► Některé jazyky (Cobol, PL/1, …) proto přišly s koncepcí
ošetření nestandardních situací
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
4
Ošetření nestandardních situací v Javě
► Výjimečná událost =
problém, který brání dalšímu vykonávání části kódu
► Událost je výjimečná v tom, že na rozdíl od běžných problémů
nemá program k vyřešení situace dost informaci
► Program může při výskytu výjimečné události vyvolat výjimku
► Výjimka (exception)
objekt určený k přenosu informací o nastalém problému
z místa jeho vzniku do místa, kde bude problém řešen
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
5
Postup při vyvolání výjimky
1. Vytvoří se výjimka = objekt typu Throwable
(prakticky vždy instance některého z potomků)
2. Vytvořená výjimka se vyhodí =
přeruší se běh programu v místě, kde výjimka vznikla,
a začne se hledat místo, kde bude daná výjimka ošetřena
3. Ošetření výjimky (handler) by mělo uvést program do stavu,
v němž může jeho vykonávání pokračovat
► Výjimka „probublává“ programem z místa vyhození stále výše
a nenarazí-li cestou nikde na své ošetření,
zachytí ji virtuální stroj, který na standardní chybový výstup
vypíše zprávu o vzniku výjimky
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
6
Systémová zpráva o vzniku výjimky
Zpráva o vzniku výjimky spolu s názvem vlákna,
v němž k výjimce došlo (zde AWT-EventQueue-0)
Popis druhu výjimky (aritmetická výjimka dělení nulou)
Informace o místě, odkud byla volána metoda,
která vyvolala metodu, v níž došlo k vyhození výjimky
Informace o místě, odkud byla volána metoda,
v níž došlo k vyhození výjimky
Úplný název třídy včetně balíčku
Copyright © 2006, Rudolf Pecinovský
Název metody
VŠE – 05
Název souboru se
zdrojovým kódem
Číslo řádku zdrojáku,
kde došlo k výjimce
7
Klíčová slova související s výjimkami
► try (zkus)
Označuje blok kódu, v němž může dojít k výjimce
► throw (hoď)
Příkaz k vyhození výjimky;
musí být následován odkazem na existující instanci
► catch (chyť)
Blok ošetřující výjimku, která je zadána jako parametr
► finally (na konec)
Blok s povinnými závěrečnými akcemi nezávisejícími
na případném vzniku výjimky
► throws (hází)
Uvození seznamu výjimek vyhazovaných danou metodou
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
8
Vyvolání a ošetření výjimky v kódu
try {
//Kód, který může vyvolat výjimky
}
catch( Typ1 id1 ) {
//Ošetření výjimek typu Typ1
}
...
catch( TypN idN ) {
//ošetření výjimek typu TypN
}
finally {
//Kód, který se na závěr VŽDY provede
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
9
Náznak činnosti – řádný průběh
nedojde k vyvolání výjimky
= nedojde k chybě
try {
příkaz1();
příkaz2();
příkaz3();
}
catch ( xxxException e ) {
příkazProOšetřeníChyby();
}
Bloky catch
catch (…..
se přeskočí
finally {
ukončovacíPříkazy();
}
dalšíPříkaz();
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
12
Náznak činnosti – ošetřený výjimka
try {
příkaz1(); Při provádění metody příkaz2
dojde k ošetřené chybě
příkaz2();
příkaz3();
Byla vyhozena výjimka
tohoto typu nebo typu
}
některého z potomků
catch ( xxxException e ) {
příkazProOšetřeníChyby();
}
Ostatní bloky catch
catch (…..
se přeskočí
finally {
ukončovacíPříkazy();
}
dalšíPříkaz();
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
13
Náznak činnosti – neošetřená výjimka
Při provádění metody příkaz2
dojde k NEošetřené chybě
try {
příkaz1();
příkaz2();
příkaz3();
}
catch ( xxxException e ) {
příkazProOšetřeníChyby();
}
Ošetření nebylo nalezeno =>
catch (…..
provede se blok finally
a opouští se metoda
finally {
ukončovacíPříkazy();
}
dalšíPříkaz();
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
14
Vyvolání výjimky
public class Xyz implements Comparable
{
public bolean compareTo( Object o )
{
if( !(o instanceOf Xyz) )
throw new ClassCastException (
"\nPokus o porovnání s neporovnatelnou"
+ " instancí " + o );
//Zjištění, kdo je větší
return vysledek;
}
}
► Instanci nemusíme vytvářet až v příkazu throw,
můžeme ji vytvořit kdykoliv před tím a pak mu ji jen předat
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
15
Vaše jistota na trhu IT
Výjimky kontrolované a
nekontrolované
►Hierarchie výjimek
►Pořadí výjimek v blocích catch
►Metody generující výjimky
►Metody třídy Throwable
►Zřetězené výjimky
►Převod kontrolovaných na nekontrolované
Charakteristika
► Výjimky, které jsou potomky třídy RuntimeException
nebo Error označujeme jako nekontrolované (unchecked),
protože překladač nekontroluje, zda je na ně program připraven
► Ostatní výjimky označujeme jako kontrolované (checked),
protože překladač kontroluje dodržení pravidel:
● Každá metoda, která může vyhodit kontrolovanou výjimku,
se musí k této skutečnosti veřejně přihlásit
● Každé použití metody, která může vyhodit kontrolovanou výjimku,
musí být buď uzavřeno v bloku try…catch,
nebo se volající metoda musí přihlásit k tomu,
že může také vyhodit danou kontrolovanou výjimku
► Nekontrolované výjimky ohlašují chyby v programu,
kontrolované výjimky očekávatelné situace,
na jejichž výskyt má být program připraven
a měl by na ně umět reagovat
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
17
Hierarchie výjimek
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
18
Pořadí výjimek v blocích catch
► Třída NumberFormatException
je potomkem třídy RuntimeException
try {
Syntaktická chyba,
......
na druhý blok catch nikdy nedojde
}
catch (RuntimeException e) {
.........
}
Obrácené pořadí bloků catch
catch (NumberFormatException e){
vše vyřeší
........
try {
}
......
}
catch (NumberFormatException e) {
.........
}
catch (RuntimeException e){
........
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
19
Metody generující výjimky
► Java vyžaduje, aby programy, které používají metody
schopné vyvolat kontrolované výjimky,
byly o této schopnosti používaných metod informovány =>
pak vědí, které výjimku musí umět zachytit a ošetřit
► Všechny kontrolované výjimky, které může metoda vyhodit,
musí deklarovat v hlavičce za klíčovým slovem throws
► Deklarace vyhazování nekontrolovaných výjimek není povinná
public void metoda()
throws KontrolovanáVýjimka1,
KontrolovanáVýjimka2
{
// Tělo metody
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
20
Metody třídy Throwable
► String getMessage()
Vrátí zprávu popisující danou výjimku
► String toString()
Vrátí název třídy výjimky následovaný případnou zprávou
► void printStackTrace()
Vytiskne toString() následovaný sadou informací o volající
posloupnosti, která vedla k vzniku výjimky
► Throwable fillInStackTrace()
Připraví nové informace o volací posloupnosti
vedoucí k místu zavolání této metody
► StackTraceElement[] getStackTrace()
Vrátí uchované informace o volací posloupnosti dané výjimky
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
21
Zřetězené výjimky
► V některých situacích je vhodné v rámci ošetření výjimky vyvolat
jinou výjimku, a přitom umožnit zjistit,
která výjimka byla prvotním hybatelem celé akce
► Řada výjimek má mezi svými konstruktory i takové,
které akceptují jako poslední parametr
odkaz na výjimku, jež byla příčinou vyvolání dané výjimky
► Chce-li se program zeptat výjimky na výjimku, která ji způsobila,
použije metodu
public Throwable getCause()
► Ve zprávě o vyvolání výjimky jsou místa, kde byla jedna výjimka
nahrazena jinou, označována textem caused by:
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
22
Ukázka výpisu při zřetězení výjimek
HighLevelException: MidLevelException: LowLevelException
at Junk.a(Junk.java:13)
at Junk.main(Junk.java:4)
Caused by: MidLevelException: LowLevelException
at Junk.c(Junk.java:23)
at Junk.b(Junk.java:17)
at Junk.a(Junk.java:11)
... 1 more
Caused by: LowLevelException
at Junk.e(Junk.java:30)
at Junk.d(Junk.java:27)
at Junk.c(Junk.java:21)
... 3 more
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
23
Převod kontrolovaných na nekontrolované
► Ošetřování kontrolovaných výjimek obtěžuje
► Víme-li, že k dané výjimce nejspíš nedojde
a ošetřujeme-li ji pouze proto, že na tom překladač trvá,
můžeme pro případ, že by k výjimce přece jenom došlo
zaměnit kontrolovanou výjimku za nekontrolovanou
public void prevod( String s ) {
try {
prověř( s );
} catch( Exception ex ) {
throw new RuntimeException( " Neprověřeno! ", ex );
}
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
24
Vaše jistota na trhu IT
Definice vlastních výjimek
►Hierarchie výjimek
►Pořadí výjimek v blocích catch
►Metody generující výjimky
►Metody třídy Throwable
►Vlastní výjimky
►Zásady správného používání výjimek
Definice vlastních výjimek
► Výjimky jsou zcela běžné třídy;
považujeme-li to proto za vhodné, můžeme definovat i vlastní
► Před definicí nové výjimky bychom si měli ujasnit,
bude-li kontrolovaná či nekontrolovaná;
podle toho definujeme jejího předka
► Název výjimek končí dle konvencí slovem Exception
před nímž je naznačena podstata dané výjimky
● IllegalArgumetnException
● NoSuchMethodException
● BadStringOperationException
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
26
Příklad vlastní kontrolované výjimky
public class VelkýPrůšvihException
extends Exception
{
public VelkýPrůšvihException() {};
public VelkýPrůšvihException( String zpráva ) {
super( zpráva );
}
public VelkýPrůšvihException(String zpráva,
Throwable původce ) {
super( zpráva, původce );
}
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
27
Test správného vyhození výjimky
► Na vytvářených programech je třeba otestovat i to,
že v definovaných situacích vyhodí požadovanou výjimku
public void testVyhozeníVýjimky()
{
try {
metodaKteráMáVyhoditVýjimku();
} catch ( VelkýPrůšvihException vpe ) {
return;
}
fail( "Nebyla vyhozena výjimka VelkýPrůšvihException" );
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
28
Zásady správného používání výjimek
1/2
Neignorujte
výjimky
try {
//Nějaký kód
}
catch(Exception e){}
► Výjimky, o nichž víte, že nemohou nastat,
převeďte na nekontrolované pro případ,
že by v budoucích verzích programu nastat mohly
► Při ošetřování výjimek, které nastat mohou,
ale nemají vliv na chod programu,
vložte do těla ošetření alespoň vysvětlující komentář
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
29
Zásady správného používání výjimek
2/2
► Používejte výjimky pouze k ošetření výjimečných stavů
► Kontrolované výjimky používejte u stavů, z nichž se lze zotavit,
jinak použijte výjimky nekontrolované
► Vyhýbejte se zbytečnému používání kontrolovaných výjimek
● Programátory ošetřování kontrolovaných výjimek obtěžuje
a mají pak tendenci je ošetřovat prázdným blokem catch
► Dávejte přednost standardním výjimkám,
vyvolávejte výjimky odpovídající dané abstrakci
● Programátoři by měli z názvu výjimky poznat, co se stalo
● Standardní výjimky mají všeobecně známý význam
► Snažte se o atomičnost selhání; i po vyhození výjimky
by měl být objekt v dobře definovaném stavu
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
30
Zásady správného používání výjimek
3/2
► Doplňujte výjimky zprávami,
výjimka by sama měla poskytnout dostatek informací
a neměla by programátora nutit k podrobnější analýze programu
► Dokumentujte vyvolávané výjimky v dokumentačních
komentářích pomocí značky @throws
► Nedělejte bloky try zbytečně velké,
kód uvnitř těchto bloků se neoptimalizuje
► Umíte-li výjimku v metodě ošetřit, udělejte to
► Detekuje-li se chyba v jedné metodě a má se ošetřit v jiné
(stejné či jiné instance), použijte výjimku.
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
31
Nejčastěji používané výjimky
1/2
► IllegalArgumentException
Byla zadána nepovolená hodnota parametru
● Např. chci nastavit zápornou velikost grafického tvaru
► IllegalStateException
V daném stavu objektu nelze metodu provést
● Např. otevřu soubor, přečtu pár vět, zavřu soubor a chci znovu přečíst větu
► NullPointerException
Byla vyvolána metoda instance, na níž ukazuje prázdný odkaz,
nebo byl předán nepovolený prázdný odkaz v parametru
► ArrayIndexOutOfBoundException
Byly zadány špatné meze pole, buď záporné nebo moc velké
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
32
Nejčastěji používané výjimky
2/2
► ConcurrentModificationException
V průběhu iterace byla změněna struktura kontejneru
● Např. byl do kontejneru přidán prvek
► NumberFormatException
Je požadován špatný převod řetězce na číslo či naopak
● Chci-li např. převést na číslo řetězec, který není číslem
● Častá chyba v metodách String.format či PrintStream.printf
► ClassCastException
Požadované přetypování není možné
► UnsupportedOperationException
Požadovaná operace není podporována
(např. chci přidat prvek do neměnného kontejneru)
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
33
Vaše jistota na trhu IT
Děkuji za pozornost
►Rudolf Pecinovský
http://vyuka.pecinovsky.cz/vse
mail: [email protected]
ICQ: 158 156 600
Slide 6
Vaše jistota na trhu IT
Výjimky
Rudolf Pecinovský
[email protected]
Vaše jistota na trhu IT
Obsah s odkazy
►Výjimky
►Výjimky kontrolované a nekontrolované
►Definice vlastních výjimek
Vaše jistota na trhu IT
Výjimky
►Výjimečné situace v programech
►Ošetření nestandardních situací v Javě
►Zpráva o výjimce
►Klíčová slova
►Činnost
►Vyvolání
Výjimečné situace v programech
► V každém programu je alespoň jedna chyba –
program na ni musí být připraven
► Starší programy
● Program vypsal chybové hlášení a ukončil činnost;
● V některých situacích (válcovací stolice, autopilot, …) nepřijatelné
● Funkce vrátí hodnotu signalizující chybu
● Programátor musí neustále testovat, co funkce vrací
● Knihovna měla pro tyto účely vyhrazenu speciální proměnnou,
do níž se v případě chyby zapsal její kód; nahlédnutím do proměnné
program zjistil kód poslední chyby
● Programátor musí neustále testovat, jaká je v proměnné hodnota
► Některé jazyky (Cobol, PL/1, …) proto přišly s koncepcí
ošetření nestandardních situací
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
4
Ošetření nestandardních situací v Javě
► Výjimečná událost =
problém, který brání dalšímu vykonávání části kódu
► Událost je výjimečná v tom, že na rozdíl od běžných problémů
nemá program k vyřešení situace dost informaci
► Program může při výskytu výjimečné události vyvolat výjimku
► Výjimka (exception)
objekt určený k přenosu informací o nastalém problému
z místa jeho vzniku do místa, kde bude problém řešen
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
5
Postup při vyvolání výjimky
1. Vytvoří se výjimka = objekt typu Throwable
(prakticky vždy instance některého z potomků)
2. Vytvořená výjimka se vyhodí =
přeruší se běh programu v místě, kde výjimka vznikla,
a začne se hledat místo, kde bude daná výjimka ošetřena
3. Ošetření výjimky (handler) by mělo uvést program do stavu,
v němž může jeho vykonávání pokračovat
► Výjimka „probublává“ programem z místa vyhození stále výše
a nenarazí-li cestou nikde na své ošetření,
zachytí ji virtuální stroj, který na standardní chybový výstup
vypíše zprávu o vzniku výjimky
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
6
Systémová zpráva o vzniku výjimky
Zpráva o vzniku výjimky spolu s názvem vlákna,
v němž k výjimce došlo (zde AWT-EventQueue-0)
Popis druhu výjimky (aritmetická výjimka dělení nulou)
Informace o místě, odkud byla volána metoda,
která vyvolala metodu, v níž došlo k vyhození výjimky
Informace o místě, odkud byla volána metoda,
v níž došlo k vyhození výjimky
Úplný název třídy včetně balíčku
Copyright © 2006, Rudolf Pecinovský
Název metody
VŠE – 05
Název souboru se
zdrojovým kódem
Číslo řádku zdrojáku,
kde došlo k výjimce
7
Klíčová slova související s výjimkami
► try (zkus)
Označuje blok kódu, v němž může dojít k výjimce
► throw (hoď)
Příkaz k vyhození výjimky;
musí být následován odkazem na existující instanci
► catch (chyť)
Blok ošetřující výjimku, která je zadána jako parametr
► finally (na konec)
Blok s povinnými závěrečnými akcemi nezávisejícími
na případném vzniku výjimky
► throws (hází)
Uvození seznamu výjimek vyhazovaných danou metodou
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
8
Vyvolání a ošetření výjimky v kódu
try {
//Kód, který může vyvolat výjimky
}
catch( Typ1 id1 ) {
//Ošetření výjimek typu Typ1
}
...
catch( TypN idN ) {
//ošetření výjimek typu TypN
}
finally {
//Kód, který se na závěr VŽDY provede
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
9
Náznak činnosti – řádný průběh
nedojde k vyvolání výjimky
= nedojde k chybě
try {
příkaz1();
příkaz2();
příkaz3();
}
catch ( xxxException e ) {
příkazProOšetřeníChyby();
}
Bloky catch
catch (…..
se přeskočí
finally {
ukončovacíPříkazy();
}
dalšíPříkaz();
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
12
Náznak činnosti – ošetřený výjimka
try {
příkaz1(); Při provádění metody příkaz2
dojde k ošetřené chybě
příkaz2();
příkaz3();
Byla vyhozena výjimka
tohoto typu nebo typu
}
některého z potomků
catch ( xxxException e ) {
příkazProOšetřeníChyby();
}
Ostatní bloky catch
catch (…..
se přeskočí
finally {
ukončovacíPříkazy();
}
dalšíPříkaz();
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
13
Náznak činnosti – neošetřená výjimka
Při provádění metody příkaz2
dojde k NEošetřené chybě
try {
příkaz1();
příkaz2();
příkaz3();
}
catch ( xxxException e ) {
příkazProOšetřeníChyby();
}
Ošetření nebylo nalezeno =>
catch (…..
provede se blok finally
a opouští se metoda
finally {
ukončovacíPříkazy();
}
dalšíPříkaz();
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
14
Vyvolání výjimky
public class Xyz implements Comparable
{
public bolean compareTo( Object o )
{
if( !(o instanceOf Xyz) )
throw new ClassCastException (
"\nPokus o porovnání s neporovnatelnou"
+ " instancí " + o );
//Zjištění, kdo je větší
return vysledek;
}
}
► Instanci nemusíme vytvářet až v příkazu throw,
můžeme ji vytvořit kdykoliv před tím a pak mu ji jen předat
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
15
Vaše jistota na trhu IT
Výjimky kontrolované a
nekontrolované
►Hierarchie výjimek
►Pořadí výjimek v blocích catch
►Metody generující výjimky
►Metody třídy Throwable
►Zřetězené výjimky
►Převod kontrolovaných na nekontrolované
Charakteristika
► Výjimky, které jsou potomky třídy RuntimeException
nebo Error označujeme jako nekontrolované (unchecked),
protože překladač nekontroluje, zda je na ně program připraven
► Ostatní výjimky označujeme jako kontrolované (checked),
protože překladač kontroluje dodržení pravidel:
● Každá metoda, která může vyhodit kontrolovanou výjimku,
se musí k této skutečnosti veřejně přihlásit
● Každé použití metody, která může vyhodit kontrolovanou výjimku,
musí být buď uzavřeno v bloku try…catch,
nebo se volající metoda musí přihlásit k tomu,
že může také vyhodit danou kontrolovanou výjimku
► Nekontrolované výjimky ohlašují chyby v programu,
kontrolované výjimky očekávatelné situace,
na jejichž výskyt má být program připraven
a měl by na ně umět reagovat
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
17
Hierarchie výjimek
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
18
Pořadí výjimek v blocích catch
► Třída NumberFormatException
je potomkem třídy RuntimeException
try {
Syntaktická chyba,
......
na druhý blok catch nikdy nedojde
}
catch (RuntimeException e) {
.........
}
Obrácené pořadí bloků catch
catch (NumberFormatException e){
vše vyřeší
........
try {
}
......
}
catch (NumberFormatException e) {
.........
}
catch (RuntimeException e){
........
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
19
Metody generující výjimky
► Java vyžaduje, aby programy, které používají metody
schopné vyvolat kontrolované výjimky,
byly o této schopnosti používaných metod informovány =>
pak vědí, které výjimku musí umět zachytit a ošetřit
► Všechny kontrolované výjimky, které může metoda vyhodit,
musí deklarovat v hlavičce za klíčovým slovem throws
► Deklarace vyhazování nekontrolovaných výjimek není povinná
public void metoda()
throws KontrolovanáVýjimka1,
KontrolovanáVýjimka2
{
// Tělo metody
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
20
Metody třídy Throwable
► String getMessage()
Vrátí zprávu popisující danou výjimku
► String toString()
Vrátí název třídy výjimky následovaný případnou zprávou
► void printStackTrace()
Vytiskne toString() následovaný sadou informací o volající
posloupnosti, která vedla k vzniku výjimky
► Throwable fillInStackTrace()
Připraví nové informace o volací posloupnosti
vedoucí k místu zavolání této metody
► StackTraceElement[] getStackTrace()
Vrátí uchované informace o volací posloupnosti dané výjimky
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
21
Zřetězené výjimky
► V některých situacích je vhodné v rámci ošetření výjimky vyvolat
jinou výjimku, a přitom umožnit zjistit,
která výjimka byla prvotním hybatelem celé akce
► Řada výjimek má mezi svými konstruktory i takové,
které akceptují jako poslední parametr
odkaz na výjimku, jež byla příčinou vyvolání dané výjimky
► Chce-li se program zeptat výjimky na výjimku, která ji způsobila,
použije metodu
public Throwable getCause()
► Ve zprávě o vyvolání výjimky jsou místa, kde byla jedna výjimka
nahrazena jinou, označována textem caused by:
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
22
Ukázka výpisu při zřetězení výjimek
HighLevelException: MidLevelException: LowLevelException
at Junk.a(Junk.java:13)
at Junk.main(Junk.java:4)
Caused by: MidLevelException: LowLevelException
at Junk.c(Junk.java:23)
at Junk.b(Junk.java:17)
at Junk.a(Junk.java:11)
... 1 more
Caused by: LowLevelException
at Junk.e(Junk.java:30)
at Junk.d(Junk.java:27)
at Junk.c(Junk.java:21)
... 3 more
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
23
Převod kontrolovaných na nekontrolované
► Ošetřování kontrolovaných výjimek obtěžuje
► Víme-li, že k dané výjimce nejspíš nedojde
a ošetřujeme-li ji pouze proto, že na tom překladač trvá,
můžeme pro případ, že by k výjimce přece jenom došlo
zaměnit kontrolovanou výjimku za nekontrolovanou
public void prevod( String s ) {
try {
prověř( s );
} catch( Exception ex ) {
throw new RuntimeException( " Neprověřeno! ", ex );
}
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
24
Vaše jistota na trhu IT
Definice vlastních výjimek
►Hierarchie výjimek
►Pořadí výjimek v blocích catch
►Metody generující výjimky
►Metody třídy Throwable
►Vlastní výjimky
►Zásady správného používání výjimek
Definice vlastních výjimek
► Výjimky jsou zcela běžné třídy;
považujeme-li to proto za vhodné, můžeme definovat i vlastní
► Před definicí nové výjimky bychom si měli ujasnit,
bude-li kontrolovaná či nekontrolovaná;
podle toho definujeme jejího předka
► Název výjimek končí dle konvencí slovem Exception
před nímž je naznačena podstata dané výjimky
● IllegalArgumetnException
● NoSuchMethodException
● BadStringOperationException
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
26
Příklad vlastní kontrolované výjimky
public class VelkýPrůšvihException
extends Exception
{
public VelkýPrůšvihException() {};
public VelkýPrůšvihException( String zpráva ) {
super( zpráva );
}
public VelkýPrůšvihException(String zpráva,
Throwable původce ) {
super( zpráva, původce );
}
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
27
Test správného vyhození výjimky
► Na vytvářených programech je třeba otestovat i to,
že v definovaných situacích vyhodí požadovanou výjimku
public void testVyhozeníVýjimky()
{
try {
metodaKteráMáVyhoditVýjimku();
} catch ( VelkýPrůšvihException vpe ) {
return;
}
fail( "Nebyla vyhozena výjimka VelkýPrůšvihException" );
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
28
Zásady správného používání výjimek
1/2
Neignorujte
výjimky
try {
//Nějaký kód
}
catch(Exception e){}
► Výjimky, o nichž víte, že nemohou nastat,
převeďte na nekontrolované pro případ,
že by v budoucích verzích programu nastat mohly
► Při ošetřování výjimek, které nastat mohou,
ale nemají vliv na chod programu,
vložte do těla ošetření alespoň vysvětlující komentář
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
29
Zásady správného používání výjimek
2/2
► Používejte výjimky pouze k ošetření výjimečných stavů
► Kontrolované výjimky používejte u stavů, z nichž se lze zotavit,
jinak použijte výjimky nekontrolované
► Vyhýbejte se zbytečnému používání kontrolovaných výjimek
● Programátory ošetřování kontrolovaných výjimek obtěžuje
a mají pak tendenci je ošetřovat prázdným blokem catch
► Dávejte přednost standardním výjimkám,
vyvolávejte výjimky odpovídající dané abstrakci
● Programátoři by měli z názvu výjimky poznat, co se stalo
● Standardní výjimky mají všeobecně známý význam
► Snažte se o atomičnost selhání; i po vyhození výjimky
by měl být objekt v dobře definovaném stavu
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
30
Zásady správného používání výjimek
3/2
► Doplňujte výjimky zprávami,
výjimka by sama měla poskytnout dostatek informací
a neměla by programátora nutit k podrobnější analýze programu
► Dokumentujte vyvolávané výjimky v dokumentačních
komentářích pomocí značky @throws
► Nedělejte bloky try zbytečně velké,
kód uvnitř těchto bloků se neoptimalizuje
► Umíte-li výjimku v metodě ošetřit, udělejte to
► Detekuje-li se chyba v jedné metodě a má se ošetřit v jiné
(stejné či jiné instance), použijte výjimku.
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
31
Nejčastěji používané výjimky
1/2
► IllegalArgumentException
Byla zadána nepovolená hodnota parametru
● Např. chci nastavit zápornou velikost grafického tvaru
► IllegalStateException
V daném stavu objektu nelze metodu provést
● Např. otevřu soubor, přečtu pár vět, zavřu soubor a chci znovu přečíst větu
► NullPointerException
Byla vyvolána metoda instance, na níž ukazuje prázdný odkaz,
nebo byl předán nepovolený prázdný odkaz v parametru
► ArrayIndexOutOfBoundException
Byly zadány špatné meze pole, buď záporné nebo moc velké
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
32
Nejčastěji používané výjimky
2/2
► ConcurrentModificationException
V průběhu iterace byla změněna struktura kontejneru
● Např. byl do kontejneru přidán prvek
► NumberFormatException
Je požadován špatný převod řetězce na číslo či naopak
● Chci-li např. převést na číslo řetězec, který není číslem
● Častá chyba v metodách String.format či PrintStream.printf
► ClassCastException
Požadované přetypování není možné
► UnsupportedOperationException
Požadovaná operace není podporována
(např. chci přidat prvek do neměnného kontejneru)
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
33
Vaše jistota na trhu IT
Děkuji za pozornost
►Rudolf Pecinovský
http://vyuka.pecinovsky.cz/vse
mail: [email protected]
ICQ: 158 156 600
Slide 7
Vaše jistota na trhu IT
Výjimky
Rudolf Pecinovský
[email protected]
Vaše jistota na trhu IT
Obsah s odkazy
►Výjimky
►Výjimky kontrolované a nekontrolované
►Definice vlastních výjimek
Vaše jistota na trhu IT
Výjimky
►Výjimečné situace v programech
►Ošetření nestandardních situací v Javě
►Zpráva o výjimce
►Klíčová slova
►Činnost
►Vyvolání
Výjimečné situace v programech
► V každém programu je alespoň jedna chyba –
program na ni musí být připraven
► Starší programy
● Program vypsal chybové hlášení a ukončil činnost;
● V některých situacích (válcovací stolice, autopilot, …) nepřijatelné
● Funkce vrátí hodnotu signalizující chybu
● Programátor musí neustále testovat, co funkce vrací
● Knihovna měla pro tyto účely vyhrazenu speciální proměnnou,
do níž se v případě chyby zapsal její kód; nahlédnutím do proměnné
program zjistil kód poslední chyby
● Programátor musí neustále testovat, jaká je v proměnné hodnota
► Některé jazyky (Cobol, PL/1, …) proto přišly s koncepcí
ošetření nestandardních situací
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
4
Ošetření nestandardních situací v Javě
► Výjimečná událost =
problém, který brání dalšímu vykonávání části kódu
► Událost je výjimečná v tom, že na rozdíl od běžných problémů
nemá program k vyřešení situace dost informaci
► Program může při výskytu výjimečné události vyvolat výjimku
► Výjimka (exception)
objekt určený k přenosu informací o nastalém problému
z místa jeho vzniku do místa, kde bude problém řešen
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
5
Postup při vyvolání výjimky
1. Vytvoří se výjimka = objekt typu Throwable
(prakticky vždy instance některého z potomků)
2. Vytvořená výjimka se vyhodí =
přeruší se běh programu v místě, kde výjimka vznikla,
a začne se hledat místo, kde bude daná výjimka ošetřena
3. Ošetření výjimky (handler) by mělo uvést program do stavu,
v němž může jeho vykonávání pokračovat
► Výjimka „probublává“ programem z místa vyhození stále výše
a nenarazí-li cestou nikde na své ošetření,
zachytí ji virtuální stroj, který na standardní chybový výstup
vypíše zprávu o vzniku výjimky
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
6
Systémová zpráva o vzniku výjimky
Zpráva o vzniku výjimky spolu s názvem vlákna,
v němž k výjimce došlo (zde AWT-EventQueue-0)
Popis druhu výjimky (aritmetická výjimka dělení nulou)
Informace o místě, odkud byla volána metoda,
která vyvolala metodu, v níž došlo k vyhození výjimky
Informace o místě, odkud byla volána metoda,
v níž došlo k vyhození výjimky
Úplný název třídy včetně balíčku
Copyright © 2006, Rudolf Pecinovský
Název metody
VŠE – 05
Název souboru se
zdrojovým kódem
Číslo řádku zdrojáku,
kde došlo k výjimce
7
Klíčová slova související s výjimkami
► try (zkus)
Označuje blok kódu, v němž může dojít k výjimce
► throw (hoď)
Příkaz k vyhození výjimky;
musí být následován odkazem na existující instanci
► catch (chyť)
Blok ošetřující výjimku, která je zadána jako parametr
► finally (na konec)
Blok s povinnými závěrečnými akcemi nezávisejícími
na případném vzniku výjimky
► throws (hází)
Uvození seznamu výjimek vyhazovaných danou metodou
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
8
Vyvolání a ošetření výjimky v kódu
try {
//Kód, který může vyvolat výjimky
}
catch( Typ1 id1 ) {
//Ošetření výjimek typu Typ1
}
...
catch( TypN idN ) {
//ošetření výjimek typu TypN
}
finally {
//Kód, který se na závěr VŽDY provede
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
9
Náznak činnosti – řádný průběh
nedojde k vyvolání výjimky
= nedojde k chybě
try {
příkaz1();
příkaz2();
příkaz3();
}
catch ( xxxException e ) {
příkazProOšetřeníChyby();
}
Bloky catch
catch (…..
se přeskočí
finally {
ukončovacíPříkazy();
}
dalšíPříkaz();
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
12
Náznak činnosti – ošetřený výjimka
try {
příkaz1(); Při provádění metody příkaz2
dojde k ošetřené chybě
příkaz2();
příkaz3();
Byla vyhozena výjimka
tohoto typu nebo typu
}
některého z potomků
catch ( xxxException e ) {
příkazProOšetřeníChyby();
}
Ostatní bloky catch
catch (…..
se přeskočí
finally {
ukončovacíPříkazy();
}
dalšíPříkaz();
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
13
Náznak činnosti – neošetřená výjimka
Při provádění metody příkaz2
dojde k NEošetřené chybě
try {
příkaz1();
příkaz2();
příkaz3();
}
catch ( xxxException e ) {
příkazProOšetřeníChyby();
}
Ošetření nebylo nalezeno =>
catch (…..
provede se blok finally
a opouští se metoda
finally {
ukončovacíPříkazy();
}
dalšíPříkaz();
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
14
Vyvolání výjimky
public class Xyz implements Comparable
{
public bolean compareTo( Object o )
{
if( !(o instanceOf Xyz) )
throw new ClassCastException (
"\nPokus o porovnání s neporovnatelnou"
+ " instancí " + o );
//Zjištění, kdo je větší
return vysledek;
}
}
► Instanci nemusíme vytvářet až v příkazu throw,
můžeme ji vytvořit kdykoliv před tím a pak mu ji jen předat
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
15
Vaše jistota na trhu IT
Výjimky kontrolované a
nekontrolované
►Hierarchie výjimek
►Pořadí výjimek v blocích catch
►Metody generující výjimky
►Metody třídy Throwable
►Zřetězené výjimky
►Převod kontrolovaných na nekontrolované
Charakteristika
► Výjimky, které jsou potomky třídy RuntimeException
nebo Error označujeme jako nekontrolované (unchecked),
protože překladač nekontroluje, zda je na ně program připraven
► Ostatní výjimky označujeme jako kontrolované (checked),
protože překladač kontroluje dodržení pravidel:
● Každá metoda, která může vyhodit kontrolovanou výjimku,
se musí k této skutečnosti veřejně přihlásit
● Každé použití metody, která může vyhodit kontrolovanou výjimku,
musí být buď uzavřeno v bloku try…catch,
nebo se volající metoda musí přihlásit k tomu,
že může také vyhodit danou kontrolovanou výjimku
► Nekontrolované výjimky ohlašují chyby v programu,
kontrolované výjimky očekávatelné situace,
na jejichž výskyt má být program připraven
a měl by na ně umět reagovat
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
17
Hierarchie výjimek
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
18
Pořadí výjimek v blocích catch
► Třída NumberFormatException
je potomkem třídy RuntimeException
try {
Syntaktická chyba,
......
na druhý blok catch nikdy nedojde
}
catch (RuntimeException e) {
.........
}
Obrácené pořadí bloků catch
catch (NumberFormatException e){
vše vyřeší
........
try {
}
......
}
catch (NumberFormatException e) {
.........
}
catch (RuntimeException e){
........
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
19
Metody generující výjimky
► Java vyžaduje, aby programy, které používají metody
schopné vyvolat kontrolované výjimky,
byly o této schopnosti používaných metod informovány =>
pak vědí, které výjimku musí umět zachytit a ošetřit
► Všechny kontrolované výjimky, které může metoda vyhodit,
musí deklarovat v hlavičce za klíčovým slovem throws
► Deklarace vyhazování nekontrolovaných výjimek není povinná
public void metoda()
throws KontrolovanáVýjimka1,
KontrolovanáVýjimka2
{
// Tělo metody
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
20
Metody třídy Throwable
► String getMessage()
Vrátí zprávu popisující danou výjimku
► String toString()
Vrátí název třídy výjimky následovaný případnou zprávou
► void printStackTrace()
Vytiskne toString() následovaný sadou informací o volající
posloupnosti, která vedla k vzniku výjimky
► Throwable fillInStackTrace()
Připraví nové informace o volací posloupnosti
vedoucí k místu zavolání této metody
► StackTraceElement[] getStackTrace()
Vrátí uchované informace o volací posloupnosti dané výjimky
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
21
Zřetězené výjimky
► V některých situacích je vhodné v rámci ošetření výjimky vyvolat
jinou výjimku, a přitom umožnit zjistit,
která výjimka byla prvotním hybatelem celé akce
► Řada výjimek má mezi svými konstruktory i takové,
které akceptují jako poslední parametr
odkaz na výjimku, jež byla příčinou vyvolání dané výjimky
► Chce-li se program zeptat výjimky na výjimku, která ji způsobila,
použije metodu
public Throwable getCause()
► Ve zprávě o vyvolání výjimky jsou místa, kde byla jedna výjimka
nahrazena jinou, označována textem caused by:
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
22
Ukázka výpisu při zřetězení výjimek
HighLevelException: MidLevelException: LowLevelException
at Junk.a(Junk.java:13)
at Junk.main(Junk.java:4)
Caused by: MidLevelException: LowLevelException
at Junk.c(Junk.java:23)
at Junk.b(Junk.java:17)
at Junk.a(Junk.java:11)
... 1 more
Caused by: LowLevelException
at Junk.e(Junk.java:30)
at Junk.d(Junk.java:27)
at Junk.c(Junk.java:21)
... 3 more
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
23
Převod kontrolovaných na nekontrolované
► Ošetřování kontrolovaných výjimek obtěžuje
► Víme-li, že k dané výjimce nejspíš nedojde
a ošetřujeme-li ji pouze proto, že na tom překladač trvá,
můžeme pro případ, že by k výjimce přece jenom došlo
zaměnit kontrolovanou výjimku za nekontrolovanou
public void prevod( String s ) {
try {
prověř( s );
} catch( Exception ex ) {
throw new RuntimeException( " Neprověřeno! ", ex );
}
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
24
Vaše jistota na trhu IT
Definice vlastních výjimek
►Hierarchie výjimek
►Pořadí výjimek v blocích catch
►Metody generující výjimky
►Metody třídy Throwable
►Vlastní výjimky
►Zásady správného používání výjimek
Definice vlastních výjimek
► Výjimky jsou zcela běžné třídy;
považujeme-li to proto za vhodné, můžeme definovat i vlastní
► Před definicí nové výjimky bychom si měli ujasnit,
bude-li kontrolovaná či nekontrolovaná;
podle toho definujeme jejího předka
► Název výjimek končí dle konvencí slovem Exception
před nímž je naznačena podstata dané výjimky
● IllegalArgumetnException
● NoSuchMethodException
● BadStringOperationException
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
26
Příklad vlastní kontrolované výjimky
public class VelkýPrůšvihException
extends Exception
{
public VelkýPrůšvihException() {};
public VelkýPrůšvihException( String zpráva ) {
super( zpráva );
}
public VelkýPrůšvihException(String zpráva,
Throwable původce ) {
super( zpráva, původce );
}
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
27
Test správného vyhození výjimky
► Na vytvářených programech je třeba otestovat i to,
že v definovaných situacích vyhodí požadovanou výjimku
public void testVyhozeníVýjimky()
{
try {
metodaKteráMáVyhoditVýjimku();
} catch ( VelkýPrůšvihException vpe ) {
return;
}
fail( "Nebyla vyhozena výjimka VelkýPrůšvihException" );
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
28
Zásady správného používání výjimek
1/2
Neignorujte
výjimky
try {
//Nějaký kód
}
catch(Exception e){}
► Výjimky, o nichž víte, že nemohou nastat,
převeďte na nekontrolované pro případ,
že by v budoucích verzích programu nastat mohly
► Při ošetřování výjimek, které nastat mohou,
ale nemají vliv na chod programu,
vložte do těla ošetření alespoň vysvětlující komentář
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
29
Zásady správného používání výjimek
2/2
► Používejte výjimky pouze k ošetření výjimečných stavů
► Kontrolované výjimky používejte u stavů, z nichž se lze zotavit,
jinak použijte výjimky nekontrolované
► Vyhýbejte se zbytečnému používání kontrolovaných výjimek
● Programátory ošetřování kontrolovaných výjimek obtěžuje
a mají pak tendenci je ošetřovat prázdným blokem catch
► Dávejte přednost standardním výjimkám,
vyvolávejte výjimky odpovídající dané abstrakci
● Programátoři by měli z názvu výjimky poznat, co se stalo
● Standardní výjimky mají všeobecně známý význam
► Snažte se o atomičnost selhání; i po vyhození výjimky
by měl být objekt v dobře definovaném stavu
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
30
Zásady správného používání výjimek
3/2
► Doplňujte výjimky zprávami,
výjimka by sama měla poskytnout dostatek informací
a neměla by programátora nutit k podrobnější analýze programu
► Dokumentujte vyvolávané výjimky v dokumentačních
komentářích pomocí značky @throws
► Nedělejte bloky try zbytečně velké,
kód uvnitř těchto bloků se neoptimalizuje
► Umíte-li výjimku v metodě ošetřit, udělejte to
► Detekuje-li se chyba v jedné metodě a má se ošetřit v jiné
(stejné či jiné instance), použijte výjimku.
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
31
Nejčastěji používané výjimky
1/2
► IllegalArgumentException
Byla zadána nepovolená hodnota parametru
● Např. chci nastavit zápornou velikost grafického tvaru
► IllegalStateException
V daném stavu objektu nelze metodu provést
● Např. otevřu soubor, přečtu pár vět, zavřu soubor a chci znovu přečíst větu
► NullPointerException
Byla vyvolána metoda instance, na níž ukazuje prázdný odkaz,
nebo byl předán nepovolený prázdný odkaz v parametru
► ArrayIndexOutOfBoundException
Byly zadány špatné meze pole, buď záporné nebo moc velké
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
32
Nejčastěji používané výjimky
2/2
► ConcurrentModificationException
V průběhu iterace byla změněna struktura kontejneru
● Např. byl do kontejneru přidán prvek
► NumberFormatException
Je požadován špatný převod řetězce na číslo či naopak
● Chci-li např. převést na číslo řetězec, který není číslem
● Častá chyba v metodách String.format či PrintStream.printf
► ClassCastException
Požadované přetypování není možné
► UnsupportedOperationException
Požadovaná operace není podporována
(např. chci přidat prvek do neměnného kontejneru)
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
33
Vaše jistota na trhu IT
Děkuji za pozornost
►Rudolf Pecinovský
http://vyuka.pecinovsky.cz/vse
mail: [email protected]
ICQ: 158 156 600
Slide 8
Vaše jistota na trhu IT
Výjimky
Rudolf Pecinovský
[email protected]
Vaše jistota na trhu IT
Obsah s odkazy
►Výjimky
►Výjimky kontrolované a nekontrolované
►Definice vlastních výjimek
Vaše jistota na trhu IT
Výjimky
►Výjimečné situace v programech
►Ošetření nestandardních situací v Javě
►Zpráva o výjimce
►Klíčová slova
►Činnost
►Vyvolání
Výjimečné situace v programech
► V každém programu je alespoň jedna chyba –
program na ni musí být připraven
► Starší programy
● Program vypsal chybové hlášení a ukončil činnost;
● V některých situacích (válcovací stolice, autopilot, …) nepřijatelné
● Funkce vrátí hodnotu signalizující chybu
● Programátor musí neustále testovat, co funkce vrací
● Knihovna měla pro tyto účely vyhrazenu speciální proměnnou,
do níž se v případě chyby zapsal její kód; nahlédnutím do proměnné
program zjistil kód poslední chyby
● Programátor musí neustále testovat, jaká je v proměnné hodnota
► Některé jazyky (Cobol, PL/1, …) proto přišly s koncepcí
ošetření nestandardních situací
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
4
Ošetření nestandardních situací v Javě
► Výjimečná událost =
problém, který brání dalšímu vykonávání části kódu
► Událost je výjimečná v tom, že na rozdíl od běžných problémů
nemá program k vyřešení situace dost informaci
► Program může při výskytu výjimečné události vyvolat výjimku
► Výjimka (exception)
objekt určený k přenosu informací o nastalém problému
z místa jeho vzniku do místa, kde bude problém řešen
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
5
Postup při vyvolání výjimky
1. Vytvoří se výjimka = objekt typu Throwable
(prakticky vždy instance některého z potomků)
2. Vytvořená výjimka se vyhodí =
přeruší se běh programu v místě, kde výjimka vznikla,
a začne se hledat místo, kde bude daná výjimka ošetřena
3. Ošetření výjimky (handler) by mělo uvést program do stavu,
v němž může jeho vykonávání pokračovat
► Výjimka „probublává“ programem z místa vyhození stále výše
a nenarazí-li cestou nikde na své ošetření,
zachytí ji virtuální stroj, který na standardní chybový výstup
vypíše zprávu o vzniku výjimky
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
6
Systémová zpráva o vzniku výjimky
Zpráva o vzniku výjimky spolu s názvem vlákna,
v němž k výjimce došlo (zde AWT-EventQueue-0)
Popis druhu výjimky (aritmetická výjimka dělení nulou)
Informace o místě, odkud byla volána metoda,
která vyvolala metodu, v níž došlo k vyhození výjimky
Informace o místě, odkud byla volána metoda,
v níž došlo k vyhození výjimky
Úplný název třídy včetně balíčku
Copyright © 2006, Rudolf Pecinovský
Název metody
VŠE – 05
Název souboru se
zdrojovým kódem
Číslo řádku zdrojáku,
kde došlo k výjimce
7
Klíčová slova související s výjimkami
► try (zkus)
Označuje blok kódu, v němž může dojít k výjimce
► throw (hoď)
Příkaz k vyhození výjimky;
musí být následován odkazem na existující instanci
► catch (chyť)
Blok ošetřující výjimku, která je zadána jako parametr
► finally (na konec)
Blok s povinnými závěrečnými akcemi nezávisejícími
na případném vzniku výjimky
► throws (hází)
Uvození seznamu výjimek vyhazovaných danou metodou
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
8
Vyvolání a ošetření výjimky v kódu
try {
//Kód, který může vyvolat výjimky
}
catch( Typ1 id1 ) {
//Ošetření výjimek typu Typ1
}
...
catch( TypN idN ) {
//ošetření výjimek typu TypN
}
finally {
//Kód, který se na závěr VŽDY provede
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
9
Náznak činnosti – řádný průběh
nedojde k vyvolání výjimky
= nedojde k chybě
try {
příkaz1();
příkaz2();
příkaz3();
}
catch ( xxxException e ) {
příkazProOšetřeníChyby();
}
Bloky catch
catch (…..
se přeskočí
finally {
ukončovacíPříkazy();
}
dalšíPříkaz();
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
12
Náznak činnosti – ošetřený výjimka
try {
příkaz1(); Při provádění metody příkaz2
dojde k ošetřené chybě
příkaz2();
příkaz3();
Byla vyhozena výjimka
tohoto typu nebo typu
}
některého z potomků
catch ( xxxException e ) {
příkazProOšetřeníChyby();
}
Ostatní bloky catch
catch (…..
se přeskočí
finally {
ukončovacíPříkazy();
}
dalšíPříkaz();
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
13
Náznak činnosti – neošetřená výjimka
Při provádění metody příkaz2
dojde k NEošetřené chybě
try {
příkaz1();
příkaz2();
příkaz3();
}
catch ( xxxException e ) {
příkazProOšetřeníChyby();
}
Ošetření nebylo nalezeno =>
catch (…..
provede se blok finally
a opouští se metoda
finally {
ukončovacíPříkazy();
}
dalšíPříkaz();
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
14
Vyvolání výjimky
public class Xyz implements Comparable
{
public bolean compareTo( Object o )
{
if( !(o instanceOf Xyz) )
throw new ClassCastException (
"\nPokus o porovnání s neporovnatelnou"
+ " instancí " + o );
//Zjištění, kdo je větší
return vysledek;
}
}
► Instanci nemusíme vytvářet až v příkazu throw,
můžeme ji vytvořit kdykoliv před tím a pak mu ji jen předat
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
15
Vaše jistota na trhu IT
Výjimky kontrolované a
nekontrolované
►Hierarchie výjimek
►Pořadí výjimek v blocích catch
►Metody generující výjimky
►Metody třídy Throwable
►Zřetězené výjimky
►Převod kontrolovaných na nekontrolované
Charakteristika
► Výjimky, které jsou potomky třídy RuntimeException
nebo Error označujeme jako nekontrolované (unchecked),
protože překladač nekontroluje, zda je na ně program připraven
► Ostatní výjimky označujeme jako kontrolované (checked),
protože překladač kontroluje dodržení pravidel:
● Každá metoda, která může vyhodit kontrolovanou výjimku,
se musí k této skutečnosti veřejně přihlásit
● Každé použití metody, která může vyhodit kontrolovanou výjimku,
musí být buď uzavřeno v bloku try…catch,
nebo se volající metoda musí přihlásit k tomu,
že může také vyhodit danou kontrolovanou výjimku
► Nekontrolované výjimky ohlašují chyby v programu,
kontrolované výjimky očekávatelné situace,
na jejichž výskyt má být program připraven
a měl by na ně umět reagovat
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
17
Hierarchie výjimek
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
18
Pořadí výjimek v blocích catch
► Třída NumberFormatException
je potomkem třídy RuntimeException
try {
Syntaktická chyba,
......
na druhý blok catch nikdy nedojde
}
catch (RuntimeException e) {
.........
}
Obrácené pořadí bloků catch
catch (NumberFormatException e){
vše vyřeší
........
try {
}
......
}
catch (NumberFormatException e) {
.........
}
catch (RuntimeException e){
........
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
19
Metody generující výjimky
► Java vyžaduje, aby programy, které používají metody
schopné vyvolat kontrolované výjimky,
byly o této schopnosti používaných metod informovány =>
pak vědí, které výjimku musí umět zachytit a ošetřit
► Všechny kontrolované výjimky, které může metoda vyhodit,
musí deklarovat v hlavičce za klíčovým slovem throws
► Deklarace vyhazování nekontrolovaných výjimek není povinná
public void metoda()
throws KontrolovanáVýjimka1,
KontrolovanáVýjimka2
{
// Tělo metody
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
20
Metody třídy Throwable
► String getMessage()
Vrátí zprávu popisující danou výjimku
► String toString()
Vrátí název třídy výjimky následovaný případnou zprávou
► void printStackTrace()
Vytiskne toString() následovaný sadou informací o volající
posloupnosti, která vedla k vzniku výjimky
► Throwable fillInStackTrace()
Připraví nové informace o volací posloupnosti
vedoucí k místu zavolání této metody
► StackTraceElement[] getStackTrace()
Vrátí uchované informace o volací posloupnosti dané výjimky
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
21
Zřetězené výjimky
► V některých situacích je vhodné v rámci ošetření výjimky vyvolat
jinou výjimku, a přitom umožnit zjistit,
která výjimka byla prvotním hybatelem celé akce
► Řada výjimek má mezi svými konstruktory i takové,
které akceptují jako poslední parametr
odkaz na výjimku, jež byla příčinou vyvolání dané výjimky
► Chce-li se program zeptat výjimky na výjimku, která ji způsobila,
použije metodu
public Throwable getCause()
► Ve zprávě o vyvolání výjimky jsou místa, kde byla jedna výjimka
nahrazena jinou, označována textem caused by:
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
22
Ukázka výpisu při zřetězení výjimek
HighLevelException: MidLevelException: LowLevelException
at Junk.a(Junk.java:13)
at Junk.main(Junk.java:4)
Caused by: MidLevelException: LowLevelException
at Junk.c(Junk.java:23)
at Junk.b(Junk.java:17)
at Junk.a(Junk.java:11)
... 1 more
Caused by: LowLevelException
at Junk.e(Junk.java:30)
at Junk.d(Junk.java:27)
at Junk.c(Junk.java:21)
... 3 more
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
23
Převod kontrolovaných na nekontrolované
► Ošetřování kontrolovaných výjimek obtěžuje
► Víme-li, že k dané výjimce nejspíš nedojde
a ošetřujeme-li ji pouze proto, že na tom překladač trvá,
můžeme pro případ, že by k výjimce přece jenom došlo
zaměnit kontrolovanou výjimku za nekontrolovanou
public void prevod( String s ) {
try {
prověř( s );
} catch( Exception ex ) {
throw new RuntimeException( " Neprověřeno! ", ex );
}
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
24
Vaše jistota na trhu IT
Definice vlastních výjimek
►Hierarchie výjimek
►Pořadí výjimek v blocích catch
►Metody generující výjimky
►Metody třídy Throwable
►Vlastní výjimky
►Zásady správného používání výjimek
Definice vlastních výjimek
► Výjimky jsou zcela běžné třídy;
považujeme-li to proto za vhodné, můžeme definovat i vlastní
► Před definicí nové výjimky bychom si měli ujasnit,
bude-li kontrolovaná či nekontrolovaná;
podle toho definujeme jejího předka
► Název výjimek končí dle konvencí slovem Exception
před nímž je naznačena podstata dané výjimky
● IllegalArgumetnException
● NoSuchMethodException
● BadStringOperationException
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
26
Příklad vlastní kontrolované výjimky
public class VelkýPrůšvihException
extends Exception
{
public VelkýPrůšvihException() {};
public VelkýPrůšvihException( String zpráva ) {
super( zpráva );
}
public VelkýPrůšvihException(String zpráva,
Throwable původce ) {
super( zpráva, původce );
}
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
27
Test správného vyhození výjimky
► Na vytvářených programech je třeba otestovat i to,
že v definovaných situacích vyhodí požadovanou výjimku
public void testVyhozeníVýjimky()
{
try {
metodaKteráMáVyhoditVýjimku();
} catch ( VelkýPrůšvihException vpe ) {
return;
}
fail( "Nebyla vyhozena výjimka VelkýPrůšvihException" );
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
28
Zásady správného používání výjimek
1/2
Neignorujte
výjimky
try {
//Nějaký kód
}
catch(Exception e){}
► Výjimky, o nichž víte, že nemohou nastat,
převeďte na nekontrolované pro případ,
že by v budoucích verzích programu nastat mohly
► Při ošetřování výjimek, které nastat mohou,
ale nemají vliv na chod programu,
vložte do těla ošetření alespoň vysvětlující komentář
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
29
Zásady správného používání výjimek
2/2
► Používejte výjimky pouze k ošetření výjimečných stavů
► Kontrolované výjimky používejte u stavů, z nichž se lze zotavit,
jinak použijte výjimky nekontrolované
► Vyhýbejte se zbytečnému používání kontrolovaných výjimek
● Programátory ošetřování kontrolovaných výjimek obtěžuje
a mají pak tendenci je ošetřovat prázdným blokem catch
► Dávejte přednost standardním výjimkám,
vyvolávejte výjimky odpovídající dané abstrakci
● Programátoři by měli z názvu výjimky poznat, co se stalo
● Standardní výjimky mají všeobecně známý význam
► Snažte se o atomičnost selhání; i po vyhození výjimky
by měl být objekt v dobře definovaném stavu
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
30
Zásady správného používání výjimek
3/2
► Doplňujte výjimky zprávami,
výjimka by sama měla poskytnout dostatek informací
a neměla by programátora nutit k podrobnější analýze programu
► Dokumentujte vyvolávané výjimky v dokumentačních
komentářích pomocí značky @throws
► Nedělejte bloky try zbytečně velké,
kód uvnitř těchto bloků se neoptimalizuje
► Umíte-li výjimku v metodě ošetřit, udělejte to
► Detekuje-li se chyba v jedné metodě a má se ošetřit v jiné
(stejné či jiné instance), použijte výjimku.
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
31
Nejčastěji používané výjimky
1/2
► IllegalArgumentException
Byla zadána nepovolená hodnota parametru
● Např. chci nastavit zápornou velikost grafického tvaru
► IllegalStateException
V daném stavu objektu nelze metodu provést
● Např. otevřu soubor, přečtu pár vět, zavřu soubor a chci znovu přečíst větu
► NullPointerException
Byla vyvolána metoda instance, na níž ukazuje prázdný odkaz,
nebo byl předán nepovolený prázdný odkaz v parametru
► ArrayIndexOutOfBoundException
Byly zadány špatné meze pole, buď záporné nebo moc velké
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
32
Nejčastěji používané výjimky
2/2
► ConcurrentModificationException
V průběhu iterace byla změněna struktura kontejneru
● Např. byl do kontejneru přidán prvek
► NumberFormatException
Je požadován špatný převod řetězce na číslo či naopak
● Chci-li např. převést na číslo řetězec, který není číslem
● Častá chyba v metodách String.format či PrintStream.printf
► ClassCastException
Požadované přetypování není možné
► UnsupportedOperationException
Požadovaná operace není podporována
(např. chci přidat prvek do neměnného kontejneru)
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
33
Vaše jistota na trhu IT
Děkuji za pozornost
►Rudolf Pecinovský
http://vyuka.pecinovsky.cz/vse
mail: [email protected]
ICQ: 158 156 600
Slide 9
Vaše jistota na trhu IT
Výjimky
Rudolf Pecinovský
[email protected]
Vaše jistota na trhu IT
Obsah s odkazy
►Výjimky
►Výjimky kontrolované a nekontrolované
►Definice vlastních výjimek
Vaše jistota na trhu IT
Výjimky
►Výjimečné situace v programech
►Ošetření nestandardních situací v Javě
►Zpráva o výjimce
►Klíčová slova
►Činnost
►Vyvolání
Výjimečné situace v programech
► V každém programu je alespoň jedna chyba –
program na ni musí být připraven
► Starší programy
● Program vypsal chybové hlášení a ukončil činnost;
● V některých situacích (válcovací stolice, autopilot, …) nepřijatelné
● Funkce vrátí hodnotu signalizující chybu
● Programátor musí neustále testovat, co funkce vrací
● Knihovna měla pro tyto účely vyhrazenu speciální proměnnou,
do níž se v případě chyby zapsal její kód; nahlédnutím do proměnné
program zjistil kód poslední chyby
● Programátor musí neustále testovat, jaká je v proměnné hodnota
► Některé jazyky (Cobol, PL/1, …) proto přišly s koncepcí
ošetření nestandardních situací
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
4
Ošetření nestandardních situací v Javě
► Výjimečná událost =
problém, který brání dalšímu vykonávání části kódu
► Událost je výjimečná v tom, že na rozdíl od běžných problémů
nemá program k vyřešení situace dost informaci
► Program může při výskytu výjimečné události vyvolat výjimku
► Výjimka (exception)
objekt určený k přenosu informací o nastalém problému
z místa jeho vzniku do místa, kde bude problém řešen
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
5
Postup při vyvolání výjimky
1. Vytvoří se výjimka = objekt typu Throwable
(prakticky vždy instance některého z potomků)
2. Vytvořená výjimka se vyhodí =
přeruší se běh programu v místě, kde výjimka vznikla,
a začne se hledat místo, kde bude daná výjimka ošetřena
3. Ošetření výjimky (handler) by mělo uvést program do stavu,
v němž může jeho vykonávání pokračovat
► Výjimka „probublává“ programem z místa vyhození stále výše
a nenarazí-li cestou nikde na své ošetření,
zachytí ji virtuální stroj, který na standardní chybový výstup
vypíše zprávu o vzniku výjimky
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
6
Systémová zpráva o vzniku výjimky
Zpráva o vzniku výjimky spolu s názvem vlákna,
v němž k výjimce došlo (zde AWT-EventQueue-0)
Popis druhu výjimky (aritmetická výjimka dělení nulou)
Informace o místě, odkud byla volána metoda,
která vyvolala metodu, v níž došlo k vyhození výjimky
Informace o místě, odkud byla volána metoda,
v níž došlo k vyhození výjimky
Úplný název třídy včetně balíčku
Copyright © 2006, Rudolf Pecinovský
Název metody
VŠE – 05
Název souboru se
zdrojovým kódem
Číslo řádku zdrojáku,
kde došlo k výjimce
7
Klíčová slova související s výjimkami
► try (zkus)
Označuje blok kódu, v němž může dojít k výjimce
► throw (hoď)
Příkaz k vyhození výjimky;
musí být následován odkazem na existující instanci
► catch (chyť)
Blok ošetřující výjimku, která je zadána jako parametr
► finally (na konec)
Blok s povinnými závěrečnými akcemi nezávisejícími
na případném vzniku výjimky
► throws (hází)
Uvození seznamu výjimek vyhazovaných danou metodou
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
8
Vyvolání a ošetření výjimky v kódu
try {
//Kód, který může vyvolat výjimky
}
catch( Typ1 id1 ) {
//Ošetření výjimek typu Typ1
}
...
catch( TypN idN ) {
//ošetření výjimek typu TypN
}
finally {
//Kód, který se na závěr VŽDY provede
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
9
Náznak činnosti – řádný průběh
nedojde k vyvolání výjimky
= nedojde k chybě
try {
příkaz1();
příkaz2();
příkaz3();
}
catch ( xxxException e ) {
příkazProOšetřeníChyby();
}
Bloky catch
catch (…..
se přeskočí
finally {
ukončovacíPříkazy();
}
dalšíPříkaz();
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
12
Náznak činnosti – ošetřený výjimka
try {
příkaz1(); Při provádění metody příkaz2
dojde k ošetřené chybě
příkaz2();
příkaz3();
Byla vyhozena výjimka
tohoto typu nebo typu
}
některého z potomků
catch ( xxxException e ) {
příkazProOšetřeníChyby();
}
Ostatní bloky catch
catch (…..
se přeskočí
finally {
ukončovacíPříkazy();
}
dalšíPříkaz();
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
13
Náznak činnosti – neošetřená výjimka
Při provádění metody příkaz2
dojde k NEošetřené chybě
try {
příkaz1();
příkaz2();
příkaz3();
}
catch ( xxxException e ) {
příkazProOšetřeníChyby();
}
Ošetření nebylo nalezeno =>
catch (…..
provede se blok finally
a opouští se metoda
finally {
ukončovacíPříkazy();
}
dalšíPříkaz();
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
14
Vyvolání výjimky
public class Xyz implements Comparable
{
public bolean compareTo( Object o )
{
if( !(o instanceOf Xyz) )
throw new ClassCastException (
"\nPokus o porovnání s neporovnatelnou"
+ " instancí " + o );
//Zjištění, kdo je větší
return vysledek;
}
}
► Instanci nemusíme vytvářet až v příkazu throw,
můžeme ji vytvořit kdykoliv před tím a pak mu ji jen předat
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
15
Vaše jistota na trhu IT
Výjimky kontrolované a
nekontrolované
►Hierarchie výjimek
►Pořadí výjimek v blocích catch
►Metody generující výjimky
►Metody třídy Throwable
►Zřetězené výjimky
►Převod kontrolovaných na nekontrolované
Charakteristika
► Výjimky, které jsou potomky třídy RuntimeException
nebo Error označujeme jako nekontrolované (unchecked),
protože překladač nekontroluje, zda je na ně program připraven
► Ostatní výjimky označujeme jako kontrolované (checked),
protože překladač kontroluje dodržení pravidel:
● Každá metoda, která může vyhodit kontrolovanou výjimku,
se musí k této skutečnosti veřejně přihlásit
● Každé použití metody, která může vyhodit kontrolovanou výjimku,
musí být buď uzavřeno v bloku try…catch,
nebo se volající metoda musí přihlásit k tomu,
že může také vyhodit danou kontrolovanou výjimku
► Nekontrolované výjimky ohlašují chyby v programu,
kontrolované výjimky očekávatelné situace,
na jejichž výskyt má být program připraven
a měl by na ně umět reagovat
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
17
Hierarchie výjimek
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
18
Pořadí výjimek v blocích catch
► Třída NumberFormatException
je potomkem třídy RuntimeException
try {
Syntaktická chyba,
......
na druhý blok catch nikdy nedojde
}
catch (RuntimeException e) {
.........
}
Obrácené pořadí bloků catch
catch (NumberFormatException e){
vše vyřeší
........
try {
}
......
}
catch (NumberFormatException e) {
.........
}
catch (RuntimeException e){
........
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
19
Metody generující výjimky
► Java vyžaduje, aby programy, které používají metody
schopné vyvolat kontrolované výjimky,
byly o této schopnosti používaných metod informovány =>
pak vědí, které výjimku musí umět zachytit a ošetřit
► Všechny kontrolované výjimky, které může metoda vyhodit,
musí deklarovat v hlavičce za klíčovým slovem throws
► Deklarace vyhazování nekontrolovaných výjimek není povinná
public void metoda()
throws KontrolovanáVýjimka1,
KontrolovanáVýjimka2
{
// Tělo metody
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
20
Metody třídy Throwable
► String getMessage()
Vrátí zprávu popisující danou výjimku
► String toString()
Vrátí název třídy výjimky následovaný případnou zprávou
► void printStackTrace()
Vytiskne toString() následovaný sadou informací o volající
posloupnosti, která vedla k vzniku výjimky
► Throwable fillInStackTrace()
Připraví nové informace o volací posloupnosti
vedoucí k místu zavolání této metody
► StackTraceElement[] getStackTrace()
Vrátí uchované informace o volací posloupnosti dané výjimky
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
21
Zřetězené výjimky
► V některých situacích je vhodné v rámci ošetření výjimky vyvolat
jinou výjimku, a přitom umožnit zjistit,
která výjimka byla prvotním hybatelem celé akce
► Řada výjimek má mezi svými konstruktory i takové,
které akceptují jako poslední parametr
odkaz na výjimku, jež byla příčinou vyvolání dané výjimky
► Chce-li se program zeptat výjimky na výjimku, která ji způsobila,
použije metodu
public Throwable getCause()
► Ve zprávě o vyvolání výjimky jsou místa, kde byla jedna výjimka
nahrazena jinou, označována textem caused by:
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
22
Ukázka výpisu při zřetězení výjimek
HighLevelException: MidLevelException: LowLevelException
at Junk.a(Junk.java:13)
at Junk.main(Junk.java:4)
Caused by: MidLevelException: LowLevelException
at Junk.c(Junk.java:23)
at Junk.b(Junk.java:17)
at Junk.a(Junk.java:11)
... 1 more
Caused by: LowLevelException
at Junk.e(Junk.java:30)
at Junk.d(Junk.java:27)
at Junk.c(Junk.java:21)
... 3 more
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
23
Převod kontrolovaných na nekontrolované
► Ošetřování kontrolovaných výjimek obtěžuje
► Víme-li, že k dané výjimce nejspíš nedojde
a ošetřujeme-li ji pouze proto, že na tom překladač trvá,
můžeme pro případ, že by k výjimce přece jenom došlo
zaměnit kontrolovanou výjimku za nekontrolovanou
public void prevod( String s ) {
try {
prověř( s );
} catch( Exception ex ) {
throw new RuntimeException( " Neprověřeno! ", ex );
}
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
24
Vaše jistota na trhu IT
Definice vlastních výjimek
►Hierarchie výjimek
►Pořadí výjimek v blocích catch
►Metody generující výjimky
►Metody třídy Throwable
►Vlastní výjimky
►Zásady správného používání výjimek
Definice vlastních výjimek
► Výjimky jsou zcela běžné třídy;
považujeme-li to proto za vhodné, můžeme definovat i vlastní
► Před definicí nové výjimky bychom si měli ujasnit,
bude-li kontrolovaná či nekontrolovaná;
podle toho definujeme jejího předka
► Název výjimek končí dle konvencí slovem Exception
před nímž je naznačena podstata dané výjimky
● IllegalArgumetnException
● NoSuchMethodException
● BadStringOperationException
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
26
Příklad vlastní kontrolované výjimky
public class VelkýPrůšvihException
extends Exception
{
public VelkýPrůšvihException() {};
public VelkýPrůšvihException( String zpráva ) {
super( zpráva );
}
public VelkýPrůšvihException(String zpráva,
Throwable původce ) {
super( zpráva, původce );
}
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
27
Test správného vyhození výjimky
► Na vytvářených programech je třeba otestovat i to,
že v definovaných situacích vyhodí požadovanou výjimku
public void testVyhozeníVýjimky()
{
try {
metodaKteráMáVyhoditVýjimku();
} catch ( VelkýPrůšvihException vpe ) {
return;
}
fail( "Nebyla vyhozena výjimka VelkýPrůšvihException" );
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
28
Zásady správného používání výjimek
1/2
Neignorujte
výjimky
try {
//Nějaký kód
}
catch(Exception e){}
► Výjimky, o nichž víte, že nemohou nastat,
převeďte na nekontrolované pro případ,
že by v budoucích verzích programu nastat mohly
► Při ošetřování výjimek, které nastat mohou,
ale nemají vliv na chod programu,
vložte do těla ošetření alespoň vysvětlující komentář
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
29
Zásady správného používání výjimek
2/2
► Používejte výjimky pouze k ošetření výjimečných stavů
► Kontrolované výjimky používejte u stavů, z nichž se lze zotavit,
jinak použijte výjimky nekontrolované
► Vyhýbejte se zbytečnému používání kontrolovaných výjimek
● Programátory ošetřování kontrolovaných výjimek obtěžuje
a mají pak tendenci je ošetřovat prázdným blokem catch
► Dávejte přednost standardním výjimkám,
vyvolávejte výjimky odpovídající dané abstrakci
● Programátoři by měli z názvu výjimky poznat, co se stalo
● Standardní výjimky mají všeobecně známý význam
► Snažte se o atomičnost selhání; i po vyhození výjimky
by měl být objekt v dobře definovaném stavu
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
30
Zásady správného používání výjimek
3/2
► Doplňujte výjimky zprávami,
výjimka by sama měla poskytnout dostatek informací
a neměla by programátora nutit k podrobnější analýze programu
► Dokumentujte vyvolávané výjimky v dokumentačních
komentářích pomocí značky @throws
► Nedělejte bloky try zbytečně velké,
kód uvnitř těchto bloků se neoptimalizuje
► Umíte-li výjimku v metodě ošetřit, udělejte to
► Detekuje-li se chyba v jedné metodě a má se ošetřit v jiné
(stejné či jiné instance), použijte výjimku.
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
31
Nejčastěji používané výjimky
1/2
► IllegalArgumentException
Byla zadána nepovolená hodnota parametru
● Např. chci nastavit zápornou velikost grafického tvaru
► IllegalStateException
V daném stavu objektu nelze metodu provést
● Např. otevřu soubor, přečtu pár vět, zavřu soubor a chci znovu přečíst větu
► NullPointerException
Byla vyvolána metoda instance, na níž ukazuje prázdný odkaz,
nebo byl předán nepovolený prázdný odkaz v parametru
► ArrayIndexOutOfBoundException
Byly zadány špatné meze pole, buď záporné nebo moc velké
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
32
Nejčastěji používané výjimky
2/2
► ConcurrentModificationException
V průběhu iterace byla změněna struktura kontejneru
● Např. byl do kontejneru přidán prvek
► NumberFormatException
Je požadován špatný převod řetězce na číslo či naopak
● Chci-li např. převést na číslo řetězec, který není číslem
● Častá chyba v metodách String.format či PrintStream.printf
► ClassCastException
Požadované přetypování není možné
► UnsupportedOperationException
Požadovaná operace není podporována
(např. chci přidat prvek do neměnného kontejneru)
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
33
Vaše jistota na trhu IT
Děkuji za pozornost
►Rudolf Pecinovský
http://vyuka.pecinovsky.cz/vse
mail: [email protected]
ICQ: 158 156 600
Slide 10
Vaše jistota na trhu IT
Výjimky
Rudolf Pecinovský
[email protected]
Vaše jistota na trhu IT
Obsah s odkazy
►Výjimky
►Výjimky kontrolované a nekontrolované
►Definice vlastních výjimek
Vaše jistota na trhu IT
Výjimky
►Výjimečné situace v programech
►Ošetření nestandardních situací v Javě
►Zpráva o výjimce
►Klíčová slova
►Činnost
►Vyvolání
Výjimečné situace v programech
► V každém programu je alespoň jedna chyba –
program na ni musí být připraven
► Starší programy
● Program vypsal chybové hlášení a ukončil činnost;
● V některých situacích (válcovací stolice, autopilot, …) nepřijatelné
● Funkce vrátí hodnotu signalizující chybu
● Programátor musí neustále testovat, co funkce vrací
● Knihovna měla pro tyto účely vyhrazenu speciální proměnnou,
do níž se v případě chyby zapsal její kód; nahlédnutím do proměnné
program zjistil kód poslední chyby
● Programátor musí neustále testovat, jaká je v proměnné hodnota
► Některé jazyky (Cobol, PL/1, …) proto přišly s koncepcí
ošetření nestandardních situací
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
4
Ošetření nestandardních situací v Javě
► Výjimečná událost =
problém, který brání dalšímu vykonávání části kódu
► Událost je výjimečná v tom, že na rozdíl od běžných problémů
nemá program k vyřešení situace dost informaci
► Program může při výskytu výjimečné události vyvolat výjimku
► Výjimka (exception)
objekt určený k přenosu informací o nastalém problému
z místa jeho vzniku do místa, kde bude problém řešen
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
5
Postup při vyvolání výjimky
1. Vytvoří se výjimka = objekt typu Throwable
(prakticky vždy instance některého z potomků)
2. Vytvořená výjimka se vyhodí =
přeruší se běh programu v místě, kde výjimka vznikla,
a začne se hledat místo, kde bude daná výjimka ošetřena
3. Ošetření výjimky (handler) by mělo uvést program do stavu,
v němž může jeho vykonávání pokračovat
► Výjimka „probublává“ programem z místa vyhození stále výše
a nenarazí-li cestou nikde na své ošetření,
zachytí ji virtuální stroj, který na standardní chybový výstup
vypíše zprávu o vzniku výjimky
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
6
Systémová zpráva o vzniku výjimky
Zpráva o vzniku výjimky spolu s názvem vlákna,
v němž k výjimce došlo (zde AWT-EventQueue-0)
Popis druhu výjimky (aritmetická výjimka dělení nulou)
Informace o místě, odkud byla volána metoda,
která vyvolala metodu, v níž došlo k vyhození výjimky
Informace o místě, odkud byla volána metoda,
v níž došlo k vyhození výjimky
Úplný název třídy včetně balíčku
Copyright © 2006, Rudolf Pecinovský
Název metody
VŠE – 05
Název souboru se
zdrojovým kódem
Číslo řádku zdrojáku,
kde došlo k výjimce
7
Klíčová slova související s výjimkami
► try (zkus)
Označuje blok kódu, v němž může dojít k výjimce
► throw (hoď)
Příkaz k vyhození výjimky;
musí být následován odkazem na existující instanci
► catch (chyť)
Blok ošetřující výjimku, která je zadána jako parametr
► finally (na konec)
Blok s povinnými závěrečnými akcemi nezávisejícími
na případném vzniku výjimky
► throws (hází)
Uvození seznamu výjimek vyhazovaných danou metodou
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
8
Vyvolání a ošetření výjimky v kódu
try {
//Kód, který může vyvolat výjimky
}
catch( Typ1 id1 ) {
//Ošetření výjimek typu Typ1
}
...
catch( TypN idN ) {
//ošetření výjimek typu TypN
}
finally {
//Kód, který se na závěr VŽDY provede
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
9
Náznak činnosti – řádný průběh
nedojde k vyvolání výjimky
= nedojde k chybě
try {
příkaz1();
příkaz2();
příkaz3();
}
catch ( xxxException e ) {
příkazProOšetřeníChyby();
}
Bloky catch
catch (…..
se přeskočí
finally {
ukončovacíPříkazy();
}
dalšíPříkaz();
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
12
Náznak činnosti – ošetřený výjimka
try {
příkaz1(); Při provádění metody příkaz2
dojde k ošetřené chybě
příkaz2();
příkaz3();
Byla vyhozena výjimka
tohoto typu nebo typu
}
některého z potomků
catch ( xxxException e ) {
příkazProOšetřeníChyby();
}
Ostatní bloky catch
catch (…..
se přeskočí
finally {
ukončovacíPříkazy();
}
dalšíPříkaz();
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
13
Náznak činnosti – neošetřená výjimka
Při provádění metody příkaz2
dojde k NEošetřené chybě
try {
příkaz1();
příkaz2();
příkaz3();
}
catch ( xxxException e ) {
příkazProOšetřeníChyby();
}
Ošetření nebylo nalezeno =>
catch (…..
provede se blok finally
a opouští se metoda
finally {
ukončovacíPříkazy();
}
dalšíPříkaz();
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
14
Vyvolání výjimky
public class Xyz implements Comparable
{
public bolean compareTo( Object o )
{
if( !(o instanceOf Xyz) )
throw new ClassCastException (
"\nPokus o porovnání s neporovnatelnou"
+ " instancí " + o );
//Zjištění, kdo je větší
return vysledek;
}
}
► Instanci nemusíme vytvářet až v příkazu throw,
můžeme ji vytvořit kdykoliv před tím a pak mu ji jen předat
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
15
Vaše jistota na trhu IT
Výjimky kontrolované a
nekontrolované
►Hierarchie výjimek
►Pořadí výjimek v blocích catch
►Metody generující výjimky
►Metody třídy Throwable
►Zřetězené výjimky
►Převod kontrolovaných na nekontrolované
Charakteristika
► Výjimky, které jsou potomky třídy RuntimeException
nebo Error označujeme jako nekontrolované (unchecked),
protože překladač nekontroluje, zda je na ně program připraven
► Ostatní výjimky označujeme jako kontrolované (checked),
protože překladač kontroluje dodržení pravidel:
● Každá metoda, která může vyhodit kontrolovanou výjimku,
se musí k této skutečnosti veřejně přihlásit
● Každé použití metody, která může vyhodit kontrolovanou výjimku,
musí být buď uzavřeno v bloku try…catch,
nebo se volající metoda musí přihlásit k tomu,
že může také vyhodit danou kontrolovanou výjimku
► Nekontrolované výjimky ohlašují chyby v programu,
kontrolované výjimky očekávatelné situace,
na jejichž výskyt má být program připraven
a měl by na ně umět reagovat
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
17
Hierarchie výjimek
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
18
Pořadí výjimek v blocích catch
► Třída NumberFormatException
je potomkem třídy RuntimeException
try {
Syntaktická chyba,
......
na druhý blok catch nikdy nedojde
}
catch (RuntimeException e) {
.........
}
Obrácené pořadí bloků catch
catch (NumberFormatException e){
vše vyřeší
........
try {
}
......
}
catch (NumberFormatException e) {
.........
}
catch (RuntimeException e){
........
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
19
Metody generující výjimky
► Java vyžaduje, aby programy, které používají metody
schopné vyvolat kontrolované výjimky,
byly o této schopnosti používaných metod informovány =>
pak vědí, které výjimku musí umět zachytit a ošetřit
► Všechny kontrolované výjimky, které může metoda vyhodit,
musí deklarovat v hlavičce za klíčovým slovem throws
► Deklarace vyhazování nekontrolovaných výjimek není povinná
public void metoda()
throws KontrolovanáVýjimka1,
KontrolovanáVýjimka2
{
// Tělo metody
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
20
Metody třídy Throwable
► String getMessage()
Vrátí zprávu popisující danou výjimku
► String toString()
Vrátí název třídy výjimky následovaný případnou zprávou
► void printStackTrace()
Vytiskne toString() následovaný sadou informací o volající
posloupnosti, která vedla k vzniku výjimky
► Throwable fillInStackTrace()
Připraví nové informace o volací posloupnosti
vedoucí k místu zavolání této metody
► StackTraceElement[] getStackTrace()
Vrátí uchované informace o volací posloupnosti dané výjimky
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
21
Zřetězené výjimky
► V některých situacích je vhodné v rámci ošetření výjimky vyvolat
jinou výjimku, a přitom umožnit zjistit,
která výjimka byla prvotním hybatelem celé akce
► Řada výjimek má mezi svými konstruktory i takové,
které akceptují jako poslední parametr
odkaz na výjimku, jež byla příčinou vyvolání dané výjimky
► Chce-li se program zeptat výjimky na výjimku, která ji způsobila,
použije metodu
public Throwable getCause()
► Ve zprávě o vyvolání výjimky jsou místa, kde byla jedna výjimka
nahrazena jinou, označována textem caused by:
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
22
Ukázka výpisu při zřetězení výjimek
HighLevelException: MidLevelException: LowLevelException
at Junk.a(Junk.java:13)
at Junk.main(Junk.java:4)
Caused by: MidLevelException: LowLevelException
at Junk.c(Junk.java:23)
at Junk.b(Junk.java:17)
at Junk.a(Junk.java:11)
... 1 more
Caused by: LowLevelException
at Junk.e(Junk.java:30)
at Junk.d(Junk.java:27)
at Junk.c(Junk.java:21)
... 3 more
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
23
Převod kontrolovaných na nekontrolované
► Ošetřování kontrolovaných výjimek obtěžuje
► Víme-li, že k dané výjimce nejspíš nedojde
a ošetřujeme-li ji pouze proto, že na tom překladač trvá,
můžeme pro případ, že by k výjimce přece jenom došlo
zaměnit kontrolovanou výjimku za nekontrolovanou
public void prevod( String s ) {
try {
prověř( s );
} catch( Exception ex ) {
throw new RuntimeException( " Neprověřeno! ", ex );
}
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
24
Vaše jistota na trhu IT
Definice vlastních výjimek
►Hierarchie výjimek
►Pořadí výjimek v blocích catch
►Metody generující výjimky
►Metody třídy Throwable
►Vlastní výjimky
►Zásady správného používání výjimek
Definice vlastních výjimek
► Výjimky jsou zcela běžné třídy;
považujeme-li to proto za vhodné, můžeme definovat i vlastní
► Před definicí nové výjimky bychom si měli ujasnit,
bude-li kontrolovaná či nekontrolovaná;
podle toho definujeme jejího předka
► Název výjimek končí dle konvencí slovem Exception
před nímž je naznačena podstata dané výjimky
● IllegalArgumetnException
● NoSuchMethodException
● BadStringOperationException
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
26
Příklad vlastní kontrolované výjimky
public class VelkýPrůšvihException
extends Exception
{
public VelkýPrůšvihException() {};
public VelkýPrůšvihException( String zpráva ) {
super( zpráva );
}
public VelkýPrůšvihException(String zpráva,
Throwable původce ) {
super( zpráva, původce );
}
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
27
Test správného vyhození výjimky
► Na vytvářených programech je třeba otestovat i to,
že v definovaných situacích vyhodí požadovanou výjimku
public void testVyhozeníVýjimky()
{
try {
metodaKteráMáVyhoditVýjimku();
} catch ( VelkýPrůšvihException vpe ) {
return;
}
fail( "Nebyla vyhozena výjimka VelkýPrůšvihException" );
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
28
Zásady správného používání výjimek
1/2
Neignorujte
výjimky
try {
//Nějaký kód
}
catch(Exception e){}
► Výjimky, o nichž víte, že nemohou nastat,
převeďte na nekontrolované pro případ,
že by v budoucích verzích programu nastat mohly
► Při ošetřování výjimek, které nastat mohou,
ale nemají vliv na chod programu,
vložte do těla ošetření alespoň vysvětlující komentář
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
29
Zásady správného používání výjimek
2/2
► Používejte výjimky pouze k ošetření výjimečných stavů
► Kontrolované výjimky používejte u stavů, z nichž se lze zotavit,
jinak použijte výjimky nekontrolované
► Vyhýbejte se zbytečnému používání kontrolovaných výjimek
● Programátory ošetřování kontrolovaných výjimek obtěžuje
a mají pak tendenci je ošetřovat prázdným blokem catch
► Dávejte přednost standardním výjimkám,
vyvolávejte výjimky odpovídající dané abstrakci
● Programátoři by měli z názvu výjimky poznat, co se stalo
● Standardní výjimky mají všeobecně známý význam
► Snažte se o atomičnost selhání; i po vyhození výjimky
by měl být objekt v dobře definovaném stavu
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
30
Zásady správného používání výjimek
3/2
► Doplňujte výjimky zprávami,
výjimka by sama měla poskytnout dostatek informací
a neměla by programátora nutit k podrobnější analýze programu
► Dokumentujte vyvolávané výjimky v dokumentačních
komentářích pomocí značky @throws
► Nedělejte bloky try zbytečně velké,
kód uvnitř těchto bloků se neoptimalizuje
► Umíte-li výjimku v metodě ošetřit, udělejte to
► Detekuje-li se chyba v jedné metodě a má se ošetřit v jiné
(stejné či jiné instance), použijte výjimku.
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
31
Nejčastěji používané výjimky
1/2
► IllegalArgumentException
Byla zadána nepovolená hodnota parametru
● Např. chci nastavit zápornou velikost grafického tvaru
► IllegalStateException
V daném stavu objektu nelze metodu provést
● Např. otevřu soubor, přečtu pár vět, zavřu soubor a chci znovu přečíst větu
► NullPointerException
Byla vyvolána metoda instance, na níž ukazuje prázdný odkaz,
nebo byl předán nepovolený prázdný odkaz v parametru
► ArrayIndexOutOfBoundException
Byly zadány špatné meze pole, buď záporné nebo moc velké
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
32
Nejčastěji používané výjimky
2/2
► ConcurrentModificationException
V průběhu iterace byla změněna struktura kontejneru
● Např. byl do kontejneru přidán prvek
► NumberFormatException
Je požadován špatný převod řetězce na číslo či naopak
● Chci-li např. převést na číslo řetězec, který není číslem
● Častá chyba v metodách String.format či PrintStream.printf
► ClassCastException
Požadované přetypování není možné
► UnsupportedOperationException
Požadovaná operace není podporována
(např. chci přidat prvek do neměnného kontejneru)
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
33
Vaše jistota na trhu IT
Děkuji za pozornost
►Rudolf Pecinovský
http://vyuka.pecinovsky.cz/vse
mail: [email protected]
ICQ: 158 156 600
Slide 11
Vaše jistota na trhu IT
Výjimky
Rudolf Pecinovský
[email protected]
Vaše jistota na trhu IT
Obsah s odkazy
►Výjimky
►Výjimky kontrolované a nekontrolované
►Definice vlastních výjimek
Vaše jistota na trhu IT
Výjimky
►Výjimečné situace v programech
►Ošetření nestandardních situací v Javě
►Zpráva o výjimce
►Klíčová slova
►Činnost
►Vyvolání
Výjimečné situace v programech
► V každém programu je alespoň jedna chyba –
program na ni musí být připraven
► Starší programy
● Program vypsal chybové hlášení a ukončil činnost;
● V některých situacích (válcovací stolice, autopilot, …) nepřijatelné
● Funkce vrátí hodnotu signalizující chybu
● Programátor musí neustále testovat, co funkce vrací
● Knihovna měla pro tyto účely vyhrazenu speciální proměnnou,
do níž se v případě chyby zapsal její kód; nahlédnutím do proměnné
program zjistil kód poslední chyby
● Programátor musí neustále testovat, jaká je v proměnné hodnota
► Některé jazyky (Cobol, PL/1, …) proto přišly s koncepcí
ošetření nestandardních situací
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
4
Ošetření nestandardních situací v Javě
► Výjimečná událost =
problém, který brání dalšímu vykonávání části kódu
► Událost je výjimečná v tom, že na rozdíl od běžných problémů
nemá program k vyřešení situace dost informaci
► Program může při výskytu výjimečné události vyvolat výjimku
► Výjimka (exception)
objekt určený k přenosu informací o nastalém problému
z místa jeho vzniku do místa, kde bude problém řešen
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
5
Postup při vyvolání výjimky
1. Vytvoří se výjimka = objekt typu Throwable
(prakticky vždy instance některého z potomků)
2. Vytvořená výjimka se vyhodí =
přeruší se běh programu v místě, kde výjimka vznikla,
a začne se hledat místo, kde bude daná výjimka ošetřena
3. Ošetření výjimky (handler) by mělo uvést program do stavu,
v němž může jeho vykonávání pokračovat
► Výjimka „probublává“ programem z místa vyhození stále výše
a nenarazí-li cestou nikde na své ošetření,
zachytí ji virtuální stroj, který na standardní chybový výstup
vypíše zprávu o vzniku výjimky
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
6
Systémová zpráva o vzniku výjimky
Zpráva o vzniku výjimky spolu s názvem vlákna,
v němž k výjimce došlo (zde AWT-EventQueue-0)
Popis druhu výjimky (aritmetická výjimka dělení nulou)
Informace o místě, odkud byla volána metoda,
která vyvolala metodu, v níž došlo k vyhození výjimky
Informace o místě, odkud byla volána metoda,
v níž došlo k vyhození výjimky
Úplný název třídy včetně balíčku
Copyright © 2006, Rudolf Pecinovský
Název metody
VŠE – 05
Název souboru se
zdrojovým kódem
Číslo řádku zdrojáku,
kde došlo k výjimce
7
Klíčová slova související s výjimkami
► try (zkus)
Označuje blok kódu, v němž může dojít k výjimce
► throw (hoď)
Příkaz k vyhození výjimky;
musí být následován odkazem na existující instanci
► catch (chyť)
Blok ošetřující výjimku, která je zadána jako parametr
► finally (na konec)
Blok s povinnými závěrečnými akcemi nezávisejícími
na případném vzniku výjimky
► throws (hází)
Uvození seznamu výjimek vyhazovaných danou metodou
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
8
Vyvolání a ošetření výjimky v kódu
try {
//Kód, který může vyvolat výjimky
}
catch( Typ1 id1 ) {
//Ošetření výjimek typu Typ1
}
...
catch( TypN idN ) {
//ošetření výjimek typu TypN
}
finally {
//Kód, který se na závěr VŽDY provede
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
9
Náznak činnosti – řádný průběh
nedojde k vyvolání výjimky
= nedojde k chybě
try {
příkaz1();
příkaz2();
příkaz3();
}
catch ( xxxException e ) {
příkazProOšetřeníChyby();
}
Bloky catch
catch (…..
se přeskočí
finally {
ukončovacíPříkazy();
}
dalšíPříkaz();
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
12
Náznak činnosti – ošetřený výjimka
try {
příkaz1(); Při provádění metody příkaz2
dojde k ošetřené chybě
příkaz2();
příkaz3();
Byla vyhozena výjimka
tohoto typu nebo typu
}
některého z potomků
catch ( xxxException e ) {
příkazProOšetřeníChyby();
}
Ostatní bloky catch
catch (…..
se přeskočí
finally {
ukončovacíPříkazy();
}
dalšíPříkaz();
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
13
Náznak činnosti – neošetřená výjimka
Při provádění metody příkaz2
dojde k NEošetřené chybě
try {
příkaz1();
příkaz2();
příkaz3();
}
catch ( xxxException e ) {
příkazProOšetřeníChyby();
}
Ošetření nebylo nalezeno =>
catch (…..
provede se blok finally
a opouští se metoda
finally {
ukončovacíPříkazy();
}
dalšíPříkaz();
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
14
Vyvolání výjimky
public class Xyz implements Comparable
{
public bolean compareTo( Object o )
{
if( !(o instanceOf Xyz) )
throw new ClassCastException (
"\nPokus o porovnání s neporovnatelnou"
+ " instancí " + o );
//Zjištění, kdo je větší
return vysledek;
}
}
► Instanci nemusíme vytvářet až v příkazu throw,
můžeme ji vytvořit kdykoliv před tím a pak mu ji jen předat
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
15
Vaše jistota na trhu IT
Výjimky kontrolované a
nekontrolované
►Hierarchie výjimek
►Pořadí výjimek v blocích catch
►Metody generující výjimky
►Metody třídy Throwable
►Zřetězené výjimky
►Převod kontrolovaných na nekontrolované
Charakteristika
► Výjimky, které jsou potomky třídy RuntimeException
nebo Error označujeme jako nekontrolované (unchecked),
protože překladač nekontroluje, zda je na ně program připraven
► Ostatní výjimky označujeme jako kontrolované (checked),
protože překladač kontroluje dodržení pravidel:
● Každá metoda, která může vyhodit kontrolovanou výjimku,
se musí k této skutečnosti veřejně přihlásit
● Každé použití metody, která může vyhodit kontrolovanou výjimku,
musí být buď uzavřeno v bloku try…catch,
nebo se volající metoda musí přihlásit k tomu,
že může také vyhodit danou kontrolovanou výjimku
► Nekontrolované výjimky ohlašují chyby v programu,
kontrolované výjimky očekávatelné situace,
na jejichž výskyt má být program připraven
a měl by na ně umět reagovat
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
17
Hierarchie výjimek
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
18
Pořadí výjimek v blocích catch
► Třída NumberFormatException
je potomkem třídy RuntimeException
try {
Syntaktická chyba,
......
na druhý blok catch nikdy nedojde
}
catch (RuntimeException e) {
.........
}
Obrácené pořadí bloků catch
catch (NumberFormatException e){
vše vyřeší
........
try {
}
......
}
catch (NumberFormatException e) {
.........
}
catch (RuntimeException e){
........
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
19
Metody generující výjimky
► Java vyžaduje, aby programy, které používají metody
schopné vyvolat kontrolované výjimky,
byly o této schopnosti používaných metod informovány =>
pak vědí, které výjimku musí umět zachytit a ošetřit
► Všechny kontrolované výjimky, které může metoda vyhodit,
musí deklarovat v hlavičce za klíčovým slovem throws
► Deklarace vyhazování nekontrolovaných výjimek není povinná
public void metoda()
throws KontrolovanáVýjimka1,
KontrolovanáVýjimka2
{
// Tělo metody
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
20
Metody třídy Throwable
► String getMessage()
Vrátí zprávu popisující danou výjimku
► String toString()
Vrátí název třídy výjimky následovaný případnou zprávou
► void printStackTrace()
Vytiskne toString() následovaný sadou informací o volající
posloupnosti, která vedla k vzniku výjimky
► Throwable fillInStackTrace()
Připraví nové informace o volací posloupnosti
vedoucí k místu zavolání této metody
► StackTraceElement[] getStackTrace()
Vrátí uchované informace o volací posloupnosti dané výjimky
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
21
Zřetězené výjimky
► V některých situacích je vhodné v rámci ošetření výjimky vyvolat
jinou výjimku, a přitom umožnit zjistit,
která výjimka byla prvotním hybatelem celé akce
► Řada výjimek má mezi svými konstruktory i takové,
které akceptují jako poslední parametr
odkaz na výjimku, jež byla příčinou vyvolání dané výjimky
► Chce-li se program zeptat výjimky na výjimku, která ji způsobila,
použije metodu
public Throwable getCause()
► Ve zprávě o vyvolání výjimky jsou místa, kde byla jedna výjimka
nahrazena jinou, označována textem caused by:
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
22
Ukázka výpisu při zřetězení výjimek
HighLevelException: MidLevelException: LowLevelException
at Junk.a(Junk.java:13)
at Junk.main(Junk.java:4)
Caused by: MidLevelException: LowLevelException
at Junk.c(Junk.java:23)
at Junk.b(Junk.java:17)
at Junk.a(Junk.java:11)
... 1 more
Caused by: LowLevelException
at Junk.e(Junk.java:30)
at Junk.d(Junk.java:27)
at Junk.c(Junk.java:21)
... 3 more
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
23
Převod kontrolovaných na nekontrolované
► Ošetřování kontrolovaných výjimek obtěžuje
► Víme-li, že k dané výjimce nejspíš nedojde
a ošetřujeme-li ji pouze proto, že na tom překladač trvá,
můžeme pro případ, že by k výjimce přece jenom došlo
zaměnit kontrolovanou výjimku za nekontrolovanou
public void prevod( String s ) {
try {
prověř( s );
} catch( Exception ex ) {
throw new RuntimeException( " Neprověřeno! ", ex );
}
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
24
Vaše jistota na trhu IT
Definice vlastních výjimek
►Hierarchie výjimek
►Pořadí výjimek v blocích catch
►Metody generující výjimky
►Metody třídy Throwable
►Vlastní výjimky
►Zásady správného používání výjimek
Definice vlastních výjimek
► Výjimky jsou zcela běžné třídy;
považujeme-li to proto za vhodné, můžeme definovat i vlastní
► Před definicí nové výjimky bychom si měli ujasnit,
bude-li kontrolovaná či nekontrolovaná;
podle toho definujeme jejího předka
► Název výjimek končí dle konvencí slovem Exception
před nímž je naznačena podstata dané výjimky
● IllegalArgumetnException
● NoSuchMethodException
● BadStringOperationException
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
26
Příklad vlastní kontrolované výjimky
public class VelkýPrůšvihException
extends Exception
{
public VelkýPrůšvihException() {};
public VelkýPrůšvihException( String zpráva ) {
super( zpráva );
}
public VelkýPrůšvihException(String zpráva,
Throwable původce ) {
super( zpráva, původce );
}
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
27
Test správného vyhození výjimky
► Na vytvářených programech je třeba otestovat i to,
že v definovaných situacích vyhodí požadovanou výjimku
public void testVyhozeníVýjimky()
{
try {
metodaKteráMáVyhoditVýjimku();
} catch ( VelkýPrůšvihException vpe ) {
return;
}
fail( "Nebyla vyhozena výjimka VelkýPrůšvihException" );
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
28
Zásady správného používání výjimek
1/2
Neignorujte
výjimky
try {
//Nějaký kód
}
catch(Exception e){}
► Výjimky, o nichž víte, že nemohou nastat,
převeďte na nekontrolované pro případ,
že by v budoucích verzích programu nastat mohly
► Při ošetřování výjimek, které nastat mohou,
ale nemají vliv na chod programu,
vložte do těla ošetření alespoň vysvětlující komentář
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
29
Zásady správného používání výjimek
2/2
► Používejte výjimky pouze k ošetření výjimečných stavů
► Kontrolované výjimky používejte u stavů, z nichž se lze zotavit,
jinak použijte výjimky nekontrolované
► Vyhýbejte se zbytečnému používání kontrolovaných výjimek
● Programátory ošetřování kontrolovaných výjimek obtěžuje
a mají pak tendenci je ošetřovat prázdným blokem catch
► Dávejte přednost standardním výjimkám,
vyvolávejte výjimky odpovídající dané abstrakci
● Programátoři by měli z názvu výjimky poznat, co se stalo
● Standardní výjimky mají všeobecně známý význam
► Snažte se o atomičnost selhání; i po vyhození výjimky
by měl být objekt v dobře definovaném stavu
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
30
Zásady správného používání výjimek
3/2
► Doplňujte výjimky zprávami,
výjimka by sama měla poskytnout dostatek informací
a neměla by programátora nutit k podrobnější analýze programu
► Dokumentujte vyvolávané výjimky v dokumentačních
komentářích pomocí značky @throws
► Nedělejte bloky try zbytečně velké,
kód uvnitř těchto bloků se neoptimalizuje
► Umíte-li výjimku v metodě ošetřit, udělejte to
► Detekuje-li se chyba v jedné metodě a má se ošetřit v jiné
(stejné či jiné instance), použijte výjimku.
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
31
Nejčastěji používané výjimky
1/2
► IllegalArgumentException
Byla zadána nepovolená hodnota parametru
● Např. chci nastavit zápornou velikost grafického tvaru
► IllegalStateException
V daném stavu objektu nelze metodu provést
● Např. otevřu soubor, přečtu pár vět, zavřu soubor a chci znovu přečíst větu
► NullPointerException
Byla vyvolána metoda instance, na níž ukazuje prázdný odkaz,
nebo byl předán nepovolený prázdný odkaz v parametru
► ArrayIndexOutOfBoundException
Byly zadány špatné meze pole, buď záporné nebo moc velké
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
32
Nejčastěji používané výjimky
2/2
► ConcurrentModificationException
V průběhu iterace byla změněna struktura kontejneru
● Např. byl do kontejneru přidán prvek
► NumberFormatException
Je požadován špatný převod řetězce na číslo či naopak
● Chci-li např. převést na číslo řetězec, který není číslem
● Častá chyba v metodách String.format či PrintStream.printf
► ClassCastException
Požadované přetypování není možné
► UnsupportedOperationException
Požadovaná operace není podporována
(např. chci přidat prvek do neměnného kontejneru)
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
33
Vaše jistota na trhu IT
Děkuji za pozornost
►Rudolf Pecinovský
http://vyuka.pecinovsky.cz/vse
mail: [email protected]
ICQ: 158 156 600
Slide 12
Vaše jistota na trhu IT
Výjimky
Rudolf Pecinovský
[email protected]
Vaše jistota na trhu IT
Obsah s odkazy
►Výjimky
►Výjimky kontrolované a nekontrolované
►Definice vlastních výjimek
Vaše jistota na trhu IT
Výjimky
►Výjimečné situace v programech
►Ošetření nestandardních situací v Javě
►Zpráva o výjimce
►Klíčová slova
►Činnost
►Vyvolání
Výjimečné situace v programech
► V každém programu je alespoň jedna chyba –
program na ni musí být připraven
► Starší programy
● Program vypsal chybové hlášení a ukončil činnost;
● V některých situacích (válcovací stolice, autopilot, …) nepřijatelné
● Funkce vrátí hodnotu signalizující chybu
● Programátor musí neustále testovat, co funkce vrací
● Knihovna měla pro tyto účely vyhrazenu speciální proměnnou,
do níž se v případě chyby zapsal její kód; nahlédnutím do proměnné
program zjistil kód poslední chyby
● Programátor musí neustále testovat, jaká je v proměnné hodnota
► Některé jazyky (Cobol, PL/1, …) proto přišly s koncepcí
ošetření nestandardních situací
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
4
Ošetření nestandardních situací v Javě
► Výjimečná událost =
problém, který brání dalšímu vykonávání části kódu
► Událost je výjimečná v tom, že na rozdíl od běžných problémů
nemá program k vyřešení situace dost informaci
► Program může při výskytu výjimečné události vyvolat výjimku
► Výjimka (exception)
objekt určený k přenosu informací o nastalém problému
z místa jeho vzniku do místa, kde bude problém řešen
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
5
Postup při vyvolání výjimky
1. Vytvoří se výjimka = objekt typu Throwable
(prakticky vždy instance některého z potomků)
2. Vytvořená výjimka se vyhodí =
přeruší se běh programu v místě, kde výjimka vznikla,
a začne se hledat místo, kde bude daná výjimka ošetřena
3. Ošetření výjimky (handler) by mělo uvést program do stavu,
v němž může jeho vykonávání pokračovat
► Výjimka „probublává“ programem z místa vyhození stále výše
a nenarazí-li cestou nikde na své ošetření,
zachytí ji virtuální stroj, který na standardní chybový výstup
vypíše zprávu o vzniku výjimky
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
6
Systémová zpráva o vzniku výjimky
Zpráva o vzniku výjimky spolu s názvem vlákna,
v němž k výjimce došlo (zde AWT-EventQueue-0)
Popis druhu výjimky (aritmetická výjimka dělení nulou)
Informace o místě, odkud byla volána metoda,
která vyvolala metodu, v níž došlo k vyhození výjimky
Informace o místě, odkud byla volána metoda,
v níž došlo k vyhození výjimky
Úplný název třídy včetně balíčku
Copyright © 2006, Rudolf Pecinovský
Název metody
VŠE – 05
Název souboru se
zdrojovým kódem
Číslo řádku zdrojáku,
kde došlo k výjimce
7
Klíčová slova související s výjimkami
► try (zkus)
Označuje blok kódu, v němž může dojít k výjimce
► throw (hoď)
Příkaz k vyhození výjimky;
musí být následován odkazem na existující instanci
► catch (chyť)
Blok ošetřující výjimku, která je zadána jako parametr
► finally (na konec)
Blok s povinnými závěrečnými akcemi nezávisejícími
na případném vzniku výjimky
► throws (hází)
Uvození seznamu výjimek vyhazovaných danou metodou
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
8
Vyvolání a ošetření výjimky v kódu
try {
//Kód, který může vyvolat výjimky
}
catch( Typ1 id1 ) {
//Ošetření výjimek typu Typ1
}
...
catch( TypN idN ) {
//ošetření výjimek typu TypN
}
finally {
//Kód, který se na závěr VŽDY provede
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
9
Náznak činnosti – řádný průběh
nedojde k vyvolání výjimky
= nedojde k chybě
try {
příkaz1();
příkaz2();
příkaz3();
}
catch ( xxxException e ) {
příkazProOšetřeníChyby();
}
Bloky catch
catch (…..
se přeskočí
finally {
ukončovacíPříkazy();
}
dalšíPříkaz();
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
12
Náznak činnosti – ošetřený výjimka
try {
příkaz1(); Při provádění metody příkaz2
dojde k ošetřené chybě
příkaz2();
příkaz3();
Byla vyhozena výjimka
tohoto typu nebo typu
}
některého z potomků
catch ( xxxException e ) {
příkazProOšetřeníChyby();
}
Ostatní bloky catch
catch (…..
se přeskočí
finally {
ukončovacíPříkazy();
}
dalšíPříkaz();
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
13
Náznak činnosti – neošetřená výjimka
Při provádění metody příkaz2
dojde k NEošetřené chybě
try {
příkaz1();
příkaz2();
příkaz3();
}
catch ( xxxException e ) {
příkazProOšetřeníChyby();
}
Ošetření nebylo nalezeno =>
catch (…..
provede se blok finally
a opouští se metoda
finally {
ukončovacíPříkazy();
}
dalšíPříkaz();
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
14
Vyvolání výjimky
public class Xyz implements Comparable
{
public bolean compareTo( Object o )
{
if( !(o instanceOf Xyz) )
throw new ClassCastException (
"\nPokus o porovnání s neporovnatelnou"
+ " instancí " + o );
//Zjištění, kdo je větší
return vysledek;
}
}
► Instanci nemusíme vytvářet až v příkazu throw,
můžeme ji vytvořit kdykoliv před tím a pak mu ji jen předat
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
15
Vaše jistota na trhu IT
Výjimky kontrolované a
nekontrolované
►Hierarchie výjimek
►Pořadí výjimek v blocích catch
►Metody generující výjimky
►Metody třídy Throwable
►Zřetězené výjimky
►Převod kontrolovaných na nekontrolované
Charakteristika
► Výjimky, které jsou potomky třídy RuntimeException
nebo Error označujeme jako nekontrolované (unchecked),
protože překladač nekontroluje, zda je na ně program připraven
► Ostatní výjimky označujeme jako kontrolované (checked),
protože překladač kontroluje dodržení pravidel:
● Každá metoda, která může vyhodit kontrolovanou výjimku,
se musí k této skutečnosti veřejně přihlásit
● Každé použití metody, která může vyhodit kontrolovanou výjimku,
musí být buď uzavřeno v bloku try…catch,
nebo se volající metoda musí přihlásit k tomu,
že může také vyhodit danou kontrolovanou výjimku
► Nekontrolované výjimky ohlašují chyby v programu,
kontrolované výjimky očekávatelné situace,
na jejichž výskyt má být program připraven
a měl by na ně umět reagovat
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
17
Hierarchie výjimek
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
18
Pořadí výjimek v blocích catch
► Třída NumberFormatException
je potomkem třídy RuntimeException
try {
Syntaktická chyba,
......
na druhý blok catch nikdy nedojde
}
catch (RuntimeException e) {
.........
}
Obrácené pořadí bloků catch
catch (NumberFormatException e){
vše vyřeší
........
try {
}
......
}
catch (NumberFormatException e) {
.........
}
catch (RuntimeException e){
........
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
19
Metody generující výjimky
► Java vyžaduje, aby programy, které používají metody
schopné vyvolat kontrolované výjimky,
byly o této schopnosti používaných metod informovány =>
pak vědí, které výjimku musí umět zachytit a ošetřit
► Všechny kontrolované výjimky, které může metoda vyhodit,
musí deklarovat v hlavičce za klíčovým slovem throws
► Deklarace vyhazování nekontrolovaných výjimek není povinná
public void metoda()
throws KontrolovanáVýjimka1,
KontrolovanáVýjimka2
{
// Tělo metody
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
20
Metody třídy Throwable
► String getMessage()
Vrátí zprávu popisující danou výjimku
► String toString()
Vrátí název třídy výjimky následovaný případnou zprávou
► void printStackTrace()
Vytiskne toString() následovaný sadou informací o volající
posloupnosti, která vedla k vzniku výjimky
► Throwable fillInStackTrace()
Připraví nové informace o volací posloupnosti
vedoucí k místu zavolání této metody
► StackTraceElement[] getStackTrace()
Vrátí uchované informace o volací posloupnosti dané výjimky
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
21
Zřetězené výjimky
► V některých situacích je vhodné v rámci ošetření výjimky vyvolat
jinou výjimku, a přitom umožnit zjistit,
která výjimka byla prvotním hybatelem celé akce
► Řada výjimek má mezi svými konstruktory i takové,
které akceptují jako poslední parametr
odkaz na výjimku, jež byla příčinou vyvolání dané výjimky
► Chce-li se program zeptat výjimky na výjimku, která ji způsobila,
použije metodu
public Throwable getCause()
► Ve zprávě o vyvolání výjimky jsou místa, kde byla jedna výjimka
nahrazena jinou, označována textem caused by:
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
22
Ukázka výpisu při zřetězení výjimek
HighLevelException: MidLevelException: LowLevelException
at Junk.a(Junk.java:13)
at Junk.main(Junk.java:4)
Caused by: MidLevelException: LowLevelException
at Junk.c(Junk.java:23)
at Junk.b(Junk.java:17)
at Junk.a(Junk.java:11)
... 1 more
Caused by: LowLevelException
at Junk.e(Junk.java:30)
at Junk.d(Junk.java:27)
at Junk.c(Junk.java:21)
... 3 more
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
23
Převod kontrolovaných na nekontrolované
► Ošetřování kontrolovaných výjimek obtěžuje
► Víme-li, že k dané výjimce nejspíš nedojde
a ošetřujeme-li ji pouze proto, že na tom překladač trvá,
můžeme pro případ, že by k výjimce přece jenom došlo
zaměnit kontrolovanou výjimku za nekontrolovanou
public void prevod( String s ) {
try {
prověř( s );
} catch( Exception ex ) {
throw new RuntimeException( " Neprověřeno! ", ex );
}
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
24
Vaše jistota na trhu IT
Definice vlastních výjimek
►Hierarchie výjimek
►Pořadí výjimek v blocích catch
►Metody generující výjimky
►Metody třídy Throwable
►Vlastní výjimky
►Zásady správného používání výjimek
Definice vlastních výjimek
► Výjimky jsou zcela běžné třídy;
považujeme-li to proto za vhodné, můžeme definovat i vlastní
► Před definicí nové výjimky bychom si měli ujasnit,
bude-li kontrolovaná či nekontrolovaná;
podle toho definujeme jejího předka
► Název výjimek končí dle konvencí slovem Exception
před nímž je naznačena podstata dané výjimky
● IllegalArgumetnException
● NoSuchMethodException
● BadStringOperationException
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
26
Příklad vlastní kontrolované výjimky
public class VelkýPrůšvihException
extends Exception
{
public VelkýPrůšvihException() {};
public VelkýPrůšvihException( String zpráva ) {
super( zpráva );
}
public VelkýPrůšvihException(String zpráva,
Throwable původce ) {
super( zpráva, původce );
}
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
27
Test správného vyhození výjimky
► Na vytvářených programech je třeba otestovat i to,
že v definovaných situacích vyhodí požadovanou výjimku
public void testVyhozeníVýjimky()
{
try {
metodaKteráMáVyhoditVýjimku();
} catch ( VelkýPrůšvihException vpe ) {
return;
}
fail( "Nebyla vyhozena výjimka VelkýPrůšvihException" );
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
28
Zásady správného používání výjimek
1/2
Neignorujte
výjimky
try {
//Nějaký kód
}
catch(Exception e){}
► Výjimky, o nichž víte, že nemohou nastat,
převeďte na nekontrolované pro případ,
že by v budoucích verzích programu nastat mohly
► Při ošetřování výjimek, které nastat mohou,
ale nemají vliv na chod programu,
vložte do těla ošetření alespoň vysvětlující komentář
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
29
Zásady správného používání výjimek
2/2
► Používejte výjimky pouze k ošetření výjimečných stavů
► Kontrolované výjimky používejte u stavů, z nichž se lze zotavit,
jinak použijte výjimky nekontrolované
► Vyhýbejte se zbytečnému používání kontrolovaných výjimek
● Programátory ošetřování kontrolovaných výjimek obtěžuje
a mají pak tendenci je ošetřovat prázdným blokem catch
► Dávejte přednost standardním výjimkám,
vyvolávejte výjimky odpovídající dané abstrakci
● Programátoři by měli z názvu výjimky poznat, co se stalo
● Standardní výjimky mají všeobecně známý význam
► Snažte se o atomičnost selhání; i po vyhození výjimky
by měl být objekt v dobře definovaném stavu
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
30
Zásady správného používání výjimek
3/2
► Doplňujte výjimky zprávami,
výjimka by sama měla poskytnout dostatek informací
a neměla by programátora nutit k podrobnější analýze programu
► Dokumentujte vyvolávané výjimky v dokumentačních
komentářích pomocí značky @throws
► Nedělejte bloky try zbytečně velké,
kód uvnitř těchto bloků se neoptimalizuje
► Umíte-li výjimku v metodě ošetřit, udělejte to
► Detekuje-li se chyba v jedné metodě a má se ošetřit v jiné
(stejné či jiné instance), použijte výjimku.
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
31
Nejčastěji používané výjimky
1/2
► IllegalArgumentException
Byla zadána nepovolená hodnota parametru
● Např. chci nastavit zápornou velikost grafického tvaru
► IllegalStateException
V daném stavu objektu nelze metodu provést
● Např. otevřu soubor, přečtu pár vět, zavřu soubor a chci znovu přečíst větu
► NullPointerException
Byla vyvolána metoda instance, na níž ukazuje prázdný odkaz,
nebo byl předán nepovolený prázdný odkaz v parametru
► ArrayIndexOutOfBoundException
Byly zadány špatné meze pole, buď záporné nebo moc velké
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
32
Nejčastěji používané výjimky
2/2
► ConcurrentModificationException
V průběhu iterace byla změněna struktura kontejneru
● Např. byl do kontejneru přidán prvek
► NumberFormatException
Je požadován špatný převod řetězce na číslo či naopak
● Chci-li např. převést na číslo řetězec, který není číslem
● Častá chyba v metodách String.format či PrintStream.printf
► ClassCastException
Požadované přetypování není možné
► UnsupportedOperationException
Požadovaná operace není podporována
(např. chci přidat prvek do neměnného kontejneru)
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
33
Vaše jistota na trhu IT
Děkuji za pozornost
►Rudolf Pecinovský
http://vyuka.pecinovsky.cz/vse
mail: [email protected]
ICQ: 158 156 600
Slide 13
Vaše jistota na trhu IT
Výjimky
Rudolf Pecinovský
[email protected]
Vaše jistota na trhu IT
Obsah s odkazy
►Výjimky
►Výjimky kontrolované a nekontrolované
►Definice vlastních výjimek
Vaše jistota na trhu IT
Výjimky
►Výjimečné situace v programech
►Ošetření nestandardních situací v Javě
►Zpráva o výjimce
►Klíčová slova
►Činnost
►Vyvolání
Výjimečné situace v programech
► V každém programu je alespoň jedna chyba –
program na ni musí být připraven
► Starší programy
● Program vypsal chybové hlášení a ukončil činnost;
● V některých situacích (válcovací stolice, autopilot, …) nepřijatelné
● Funkce vrátí hodnotu signalizující chybu
● Programátor musí neustále testovat, co funkce vrací
● Knihovna měla pro tyto účely vyhrazenu speciální proměnnou,
do níž se v případě chyby zapsal její kód; nahlédnutím do proměnné
program zjistil kód poslední chyby
● Programátor musí neustále testovat, jaká je v proměnné hodnota
► Některé jazyky (Cobol, PL/1, …) proto přišly s koncepcí
ošetření nestandardních situací
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
4
Ošetření nestandardních situací v Javě
► Výjimečná událost =
problém, který brání dalšímu vykonávání části kódu
► Událost je výjimečná v tom, že na rozdíl od běžných problémů
nemá program k vyřešení situace dost informaci
► Program může při výskytu výjimečné události vyvolat výjimku
► Výjimka (exception)
objekt určený k přenosu informací o nastalém problému
z místa jeho vzniku do místa, kde bude problém řešen
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
5
Postup při vyvolání výjimky
1. Vytvoří se výjimka = objekt typu Throwable
(prakticky vždy instance některého z potomků)
2. Vytvořená výjimka se vyhodí =
přeruší se běh programu v místě, kde výjimka vznikla,
a začne se hledat místo, kde bude daná výjimka ošetřena
3. Ošetření výjimky (handler) by mělo uvést program do stavu,
v němž může jeho vykonávání pokračovat
► Výjimka „probublává“ programem z místa vyhození stále výše
a nenarazí-li cestou nikde na své ošetření,
zachytí ji virtuální stroj, který na standardní chybový výstup
vypíše zprávu o vzniku výjimky
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
6
Systémová zpráva o vzniku výjimky
Zpráva o vzniku výjimky spolu s názvem vlákna,
v němž k výjimce došlo (zde AWT-EventQueue-0)
Popis druhu výjimky (aritmetická výjimka dělení nulou)
Informace o místě, odkud byla volána metoda,
která vyvolala metodu, v níž došlo k vyhození výjimky
Informace o místě, odkud byla volána metoda,
v níž došlo k vyhození výjimky
Úplný název třídy včetně balíčku
Copyright © 2006, Rudolf Pecinovský
Název metody
VŠE – 05
Název souboru se
zdrojovým kódem
Číslo řádku zdrojáku,
kde došlo k výjimce
7
Klíčová slova související s výjimkami
► try (zkus)
Označuje blok kódu, v němž může dojít k výjimce
► throw (hoď)
Příkaz k vyhození výjimky;
musí být následován odkazem na existující instanci
► catch (chyť)
Blok ošetřující výjimku, která je zadána jako parametr
► finally (na konec)
Blok s povinnými závěrečnými akcemi nezávisejícími
na případném vzniku výjimky
► throws (hází)
Uvození seznamu výjimek vyhazovaných danou metodou
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
8
Vyvolání a ošetření výjimky v kódu
try {
//Kód, který může vyvolat výjimky
}
catch( Typ1 id1 ) {
//Ošetření výjimek typu Typ1
}
...
catch( TypN idN ) {
//ošetření výjimek typu TypN
}
finally {
//Kód, který se na závěr VŽDY provede
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
9
Náznak činnosti – řádný průběh
nedojde k vyvolání výjimky
= nedojde k chybě
try {
příkaz1();
příkaz2();
příkaz3();
}
catch ( xxxException e ) {
příkazProOšetřeníChyby();
}
Bloky catch
catch (…..
se přeskočí
finally {
ukončovacíPříkazy();
}
dalšíPříkaz();
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
12
Náznak činnosti – ošetřený výjimka
try {
příkaz1(); Při provádění metody příkaz2
dojde k ošetřené chybě
příkaz2();
příkaz3();
Byla vyhozena výjimka
tohoto typu nebo typu
}
některého z potomků
catch ( xxxException e ) {
příkazProOšetřeníChyby();
}
Ostatní bloky catch
catch (…..
se přeskočí
finally {
ukončovacíPříkazy();
}
dalšíPříkaz();
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
13
Náznak činnosti – neošetřená výjimka
Při provádění metody příkaz2
dojde k NEošetřené chybě
try {
příkaz1();
příkaz2();
příkaz3();
}
catch ( xxxException e ) {
příkazProOšetřeníChyby();
}
Ošetření nebylo nalezeno =>
catch (…..
provede se blok finally
a opouští se metoda
finally {
ukončovacíPříkazy();
}
dalšíPříkaz();
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
14
Vyvolání výjimky
public class Xyz implements Comparable
{
public bolean compareTo( Object o )
{
if( !(o instanceOf Xyz) )
throw new ClassCastException (
"\nPokus o porovnání s neporovnatelnou"
+ " instancí " + o );
//Zjištění, kdo je větší
return vysledek;
}
}
► Instanci nemusíme vytvářet až v příkazu throw,
můžeme ji vytvořit kdykoliv před tím a pak mu ji jen předat
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
15
Vaše jistota na trhu IT
Výjimky kontrolované a
nekontrolované
►Hierarchie výjimek
►Pořadí výjimek v blocích catch
►Metody generující výjimky
►Metody třídy Throwable
►Zřetězené výjimky
►Převod kontrolovaných na nekontrolované
Charakteristika
► Výjimky, které jsou potomky třídy RuntimeException
nebo Error označujeme jako nekontrolované (unchecked),
protože překladač nekontroluje, zda je na ně program připraven
► Ostatní výjimky označujeme jako kontrolované (checked),
protože překladač kontroluje dodržení pravidel:
● Každá metoda, která může vyhodit kontrolovanou výjimku,
se musí k této skutečnosti veřejně přihlásit
● Každé použití metody, která může vyhodit kontrolovanou výjimku,
musí být buď uzavřeno v bloku try…catch,
nebo se volající metoda musí přihlásit k tomu,
že může také vyhodit danou kontrolovanou výjimku
► Nekontrolované výjimky ohlašují chyby v programu,
kontrolované výjimky očekávatelné situace,
na jejichž výskyt má být program připraven
a měl by na ně umět reagovat
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
17
Hierarchie výjimek
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
18
Pořadí výjimek v blocích catch
► Třída NumberFormatException
je potomkem třídy RuntimeException
try {
Syntaktická chyba,
......
na druhý blok catch nikdy nedojde
}
catch (RuntimeException e) {
.........
}
Obrácené pořadí bloků catch
catch (NumberFormatException e){
vše vyřeší
........
try {
}
......
}
catch (NumberFormatException e) {
.........
}
catch (RuntimeException e){
........
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
19
Metody generující výjimky
► Java vyžaduje, aby programy, které používají metody
schopné vyvolat kontrolované výjimky,
byly o této schopnosti používaných metod informovány =>
pak vědí, které výjimku musí umět zachytit a ošetřit
► Všechny kontrolované výjimky, které může metoda vyhodit,
musí deklarovat v hlavičce za klíčovým slovem throws
► Deklarace vyhazování nekontrolovaných výjimek není povinná
public void metoda()
throws KontrolovanáVýjimka1,
KontrolovanáVýjimka2
{
// Tělo metody
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
20
Metody třídy Throwable
► String getMessage()
Vrátí zprávu popisující danou výjimku
► String toString()
Vrátí název třídy výjimky následovaný případnou zprávou
► void printStackTrace()
Vytiskne toString() následovaný sadou informací o volající
posloupnosti, která vedla k vzniku výjimky
► Throwable fillInStackTrace()
Připraví nové informace o volací posloupnosti
vedoucí k místu zavolání této metody
► StackTraceElement[] getStackTrace()
Vrátí uchované informace o volací posloupnosti dané výjimky
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
21
Zřetězené výjimky
► V některých situacích je vhodné v rámci ošetření výjimky vyvolat
jinou výjimku, a přitom umožnit zjistit,
která výjimka byla prvotním hybatelem celé akce
► Řada výjimek má mezi svými konstruktory i takové,
které akceptují jako poslední parametr
odkaz na výjimku, jež byla příčinou vyvolání dané výjimky
► Chce-li se program zeptat výjimky na výjimku, která ji způsobila,
použije metodu
public Throwable getCause()
► Ve zprávě o vyvolání výjimky jsou místa, kde byla jedna výjimka
nahrazena jinou, označována textem caused by:
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
22
Ukázka výpisu při zřetězení výjimek
HighLevelException: MidLevelException: LowLevelException
at Junk.a(Junk.java:13)
at Junk.main(Junk.java:4)
Caused by: MidLevelException: LowLevelException
at Junk.c(Junk.java:23)
at Junk.b(Junk.java:17)
at Junk.a(Junk.java:11)
... 1 more
Caused by: LowLevelException
at Junk.e(Junk.java:30)
at Junk.d(Junk.java:27)
at Junk.c(Junk.java:21)
... 3 more
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
23
Převod kontrolovaných na nekontrolované
► Ošetřování kontrolovaných výjimek obtěžuje
► Víme-li, že k dané výjimce nejspíš nedojde
a ošetřujeme-li ji pouze proto, že na tom překladač trvá,
můžeme pro případ, že by k výjimce přece jenom došlo
zaměnit kontrolovanou výjimku za nekontrolovanou
public void prevod( String s ) {
try {
prověř( s );
} catch( Exception ex ) {
throw new RuntimeException( " Neprověřeno! ", ex );
}
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
24
Vaše jistota na trhu IT
Definice vlastních výjimek
►Hierarchie výjimek
►Pořadí výjimek v blocích catch
►Metody generující výjimky
►Metody třídy Throwable
►Vlastní výjimky
►Zásady správného používání výjimek
Definice vlastních výjimek
► Výjimky jsou zcela běžné třídy;
považujeme-li to proto za vhodné, můžeme definovat i vlastní
► Před definicí nové výjimky bychom si měli ujasnit,
bude-li kontrolovaná či nekontrolovaná;
podle toho definujeme jejího předka
► Název výjimek končí dle konvencí slovem Exception
před nímž je naznačena podstata dané výjimky
● IllegalArgumetnException
● NoSuchMethodException
● BadStringOperationException
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
26
Příklad vlastní kontrolované výjimky
public class VelkýPrůšvihException
extends Exception
{
public VelkýPrůšvihException() {};
public VelkýPrůšvihException( String zpráva ) {
super( zpráva );
}
public VelkýPrůšvihException(String zpráva,
Throwable původce ) {
super( zpráva, původce );
}
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
27
Test správného vyhození výjimky
► Na vytvářených programech je třeba otestovat i to,
že v definovaných situacích vyhodí požadovanou výjimku
public void testVyhozeníVýjimky()
{
try {
metodaKteráMáVyhoditVýjimku();
} catch ( VelkýPrůšvihException vpe ) {
return;
}
fail( "Nebyla vyhozena výjimka VelkýPrůšvihException" );
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
28
Zásady správného používání výjimek
1/2
Neignorujte
výjimky
try {
//Nějaký kód
}
catch(Exception e){}
► Výjimky, o nichž víte, že nemohou nastat,
převeďte na nekontrolované pro případ,
že by v budoucích verzích programu nastat mohly
► Při ošetřování výjimek, které nastat mohou,
ale nemají vliv na chod programu,
vložte do těla ošetření alespoň vysvětlující komentář
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
29
Zásady správného používání výjimek
2/2
► Používejte výjimky pouze k ošetření výjimečných stavů
► Kontrolované výjimky používejte u stavů, z nichž se lze zotavit,
jinak použijte výjimky nekontrolované
► Vyhýbejte se zbytečnému používání kontrolovaných výjimek
● Programátory ošetřování kontrolovaných výjimek obtěžuje
a mají pak tendenci je ošetřovat prázdným blokem catch
► Dávejte přednost standardním výjimkám,
vyvolávejte výjimky odpovídající dané abstrakci
● Programátoři by měli z názvu výjimky poznat, co se stalo
● Standardní výjimky mají všeobecně známý význam
► Snažte se o atomičnost selhání; i po vyhození výjimky
by měl být objekt v dobře definovaném stavu
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
30
Zásady správného používání výjimek
3/2
► Doplňujte výjimky zprávami,
výjimka by sama měla poskytnout dostatek informací
a neměla by programátora nutit k podrobnější analýze programu
► Dokumentujte vyvolávané výjimky v dokumentačních
komentářích pomocí značky @throws
► Nedělejte bloky try zbytečně velké,
kód uvnitř těchto bloků se neoptimalizuje
► Umíte-li výjimku v metodě ošetřit, udělejte to
► Detekuje-li se chyba v jedné metodě a má se ošetřit v jiné
(stejné či jiné instance), použijte výjimku.
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
31
Nejčastěji používané výjimky
1/2
► IllegalArgumentException
Byla zadána nepovolená hodnota parametru
● Např. chci nastavit zápornou velikost grafického tvaru
► IllegalStateException
V daném stavu objektu nelze metodu provést
● Např. otevřu soubor, přečtu pár vět, zavřu soubor a chci znovu přečíst větu
► NullPointerException
Byla vyvolána metoda instance, na níž ukazuje prázdný odkaz,
nebo byl předán nepovolený prázdný odkaz v parametru
► ArrayIndexOutOfBoundException
Byly zadány špatné meze pole, buď záporné nebo moc velké
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
32
Nejčastěji používané výjimky
2/2
► ConcurrentModificationException
V průběhu iterace byla změněna struktura kontejneru
● Např. byl do kontejneru přidán prvek
► NumberFormatException
Je požadován špatný převod řetězce na číslo či naopak
● Chci-li např. převést na číslo řetězec, který není číslem
● Častá chyba v metodách String.format či PrintStream.printf
► ClassCastException
Požadované přetypování není možné
► UnsupportedOperationException
Požadovaná operace není podporována
(např. chci přidat prvek do neměnného kontejneru)
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
33
Vaše jistota na trhu IT
Děkuji za pozornost
►Rudolf Pecinovský
http://vyuka.pecinovsky.cz/vse
mail: [email protected]
ICQ: 158 156 600
Slide 14
Vaše jistota na trhu IT
Výjimky
Rudolf Pecinovský
[email protected]
Vaše jistota na trhu IT
Obsah s odkazy
►Výjimky
►Výjimky kontrolované a nekontrolované
►Definice vlastních výjimek
Vaše jistota na trhu IT
Výjimky
►Výjimečné situace v programech
►Ošetření nestandardních situací v Javě
►Zpráva o výjimce
►Klíčová slova
►Činnost
►Vyvolání
Výjimečné situace v programech
► V každém programu je alespoň jedna chyba –
program na ni musí být připraven
► Starší programy
● Program vypsal chybové hlášení a ukončil činnost;
● V některých situacích (válcovací stolice, autopilot, …) nepřijatelné
● Funkce vrátí hodnotu signalizující chybu
● Programátor musí neustále testovat, co funkce vrací
● Knihovna měla pro tyto účely vyhrazenu speciální proměnnou,
do níž se v případě chyby zapsal její kód; nahlédnutím do proměnné
program zjistil kód poslední chyby
● Programátor musí neustále testovat, jaká je v proměnné hodnota
► Některé jazyky (Cobol, PL/1, …) proto přišly s koncepcí
ošetření nestandardních situací
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
4
Ošetření nestandardních situací v Javě
► Výjimečná událost =
problém, který brání dalšímu vykonávání části kódu
► Událost je výjimečná v tom, že na rozdíl od běžných problémů
nemá program k vyřešení situace dost informaci
► Program může při výskytu výjimečné události vyvolat výjimku
► Výjimka (exception)
objekt určený k přenosu informací o nastalém problému
z místa jeho vzniku do místa, kde bude problém řešen
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
5
Postup při vyvolání výjimky
1. Vytvoří se výjimka = objekt typu Throwable
(prakticky vždy instance některého z potomků)
2. Vytvořená výjimka se vyhodí =
přeruší se běh programu v místě, kde výjimka vznikla,
a začne se hledat místo, kde bude daná výjimka ošetřena
3. Ošetření výjimky (handler) by mělo uvést program do stavu,
v němž může jeho vykonávání pokračovat
► Výjimka „probublává“ programem z místa vyhození stále výše
a nenarazí-li cestou nikde na své ošetření,
zachytí ji virtuální stroj, který na standardní chybový výstup
vypíše zprávu o vzniku výjimky
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
6
Systémová zpráva o vzniku výjimky
Zpráva o vzniku výjimky spolu s názvem vlákna,
v němž k výjimce došlo (zde AWT-EventQueue-0)
Popis druhu výjimky (aritmetická výjimka dělení nulou)
Informace o místě, odkud byla volána metoda,
která vyvolala metodu, v níž došlo k vyhození výjimky
Informace o místě, odkud byla volána metoda,
v níž došlo k vyhození výjimky
Úplný název třídy včetně balíčku
Copyright © 2006, Rudolf Pecinovský
Název metody
VŠE – 05
Název souboru se
zdrojovým kódem
Číslo řádku zdrojáku,
kde došlo k výjimce
7
Klíčová slova související s výjimkami
► try (zkus)
Označuje blok kódu, v němž může dojít k výjimce
► throw (hoď)
Příkaz k vyhození výjimky;
musí být následován odkazem na existující instanci
► catch (chyť)
Blok ošetřující výjimku, která je zadána jako parametr
► finally (na konec)
Blok s povinnými závěrečnými akcemi nezávisejícími
na případném vzniku výjimky
► throws (hází)
Uvození seznamu výjimek vyhazovaných danou metodou
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
8
Vyvolání a ošetření výjimky v kódu
try {
//Kód, který může vyvolat výjimky
}
catch( Typ1 id1 ) {
//Ošetření výjimek typu Typ1
}
...
catch( TypN idN ) {
//ošetření výjimek typu TypN
}
finally {
//Kód, který se na závěr VŽDY provede
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
9
Náznak činnosti – řádný průběh
nedojde k vyvolání výjimky
= nedojde k chybě
try {
příkaz1();
příkaz2();
příkaz3();
}
catch ( xxxException e ) {
příkazProOšetřeníChyby();
}
Bloky catch
catch (…..
se přeskočí
finally {
ukončovacíPříkazy();
}
dalšíPříkaz();
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
12
Náznak činnosti – ošetřený výjimka
try {
příkaz1(); Při provádění metody příkaz2
dojde k ošetřené chybě
příkaz2();
příkaz3();
Byla vyhozena výjimka
tohoto typu nebo typu
}
některého z potomků
catch ( xxxException e ) {
příkazProOšetřeníChyby();
}
Ostatní bloky catch
catch (…..
se přeskočí
finally {
ukončovacíPříkazy();
}
dalšíPříkaz();
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
13
Náznak činnosti – neošetřená výjimka
Při provádění metody příkaz2
dojde k NEošetřené chybě
try {
příkaz1();
příkaz2();
příkaz3();
}
catch ( xxxException e ) {
příkazProOšetřeníChyby();
}
Ošetření nebylo nalezeno =>
catch (…..
provede se blok finally
a opouští se metoda
finally {
ukončovacíPříkazy();
}
dalšíPříkaz();
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
14
Vyvolání výjimky
public class Xyz implements Comparable
{
public bolean compareTo( Object o )
{
if( !(o instanceOf Xyz) )
throw new ClassCastException (
"\nPokus o porovnání s neporovnatelnou"
+ " instancí " + o );
//Zjištění, kdo je větší
return vysledek;
}
}
► Instanci nemusíme vytvářet až v příkazu throw,
můžeme ji vytvořit kdykoliv před tím a pak mu ji jen předat
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
15
Vaše jistota na trhu IT
Výjimky kontrolované a
nekontrolované
►Hierarchie výjimek
►Pořadí výjimek v blocích catch
►Metody generující výjimky
►Metody třídy Throwable
►Zřetězené výjimky
►Převod kontrolovaných na nekontrolované
Charakteristika
► Výjimky, které jsou potomky třídy RuntimeException
nebo Error označujeme jako nekontrolované (unchecked),
protože překladač nekontroluje, zda je na ně program připraven
► Ostatní výjimky označujeme jako kontrolované (checked),
protože překladač kontroluje dodržení pravidel:
● Každá metoda, která může vyhodit kontrolovanou výjimku,
se musí k této skutečnosti veřejně přihlásit
● Každé použití metody, která může vyhodit kontrolovanou výjimku,
musí být buď uzavřeno v bloku try…catch,
nebo se volající metoda musí přihlásit k tomu,
že může také vyhodit danou kontrolovanou výjimku
► Nekontrolované výjimky ohlašují chyby v programu,
kontrolované výjimky očekávatelné situace,
na jejichž výskyt má být program připraven
a měl by na ně umět reagovat
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
17
Hierarchie výjimek
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
18
Pořadí výjimek v blocích catch
► Třída NumberFormatException
je potomkem třídy RuntimeException
try {
Syntaktická chyba,
......
na druhý blok catch nikdy nedojde
}
catch (RuntimeException e) {
.........
}
Obrácené pořadí bloků catch
catch (NumberFormatException e){
vše vyřeší
........
try {
}
......
}
catch (NumberFormatException e) {
.........
}
catch (RuntimeException e){
........
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
19
Metody generující výjimky
► Java vyžaduje, aby programy, které používají metody
schopné vyvolat kontrolované výjimky,
byly o této schopnosti používaných metod informovány =>
pak vědí, které výjimku musí umět zachytit a ošetřit
► Všechny kontrolované výjimky, které může metoda vyhodit,
musí deklarovat v hlavičce za klíčovým slovem throws
► Deklarace vyhazování nekontrolovaných výjimek není povinná
public void metoda()
throws KontrolovanáVýjimka1,
KontrolovanáVýjimka2
{
// Tělo metody
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
20
Metody třídy Throwable
► String getMessage()
Vrátí zprávu popisující danou výjimku
► String toString()
Vrátí název třídy výjimky následovaný případnou zprávou
► void printStackTrace()
Vytiskne toString() následovaný sadou informací o volající
posloupnosti, která vedla k vzniku výjimky
► Throwable fillInStackTrace()
Připraví nové informace o volací posloupnosti
vedoucí k místu zavolání této metody
► StackTraceElement[] getStackTrace()
Vrátí uchované informace o volací posloupnosti dané výjimky
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
21
Zřetězené výjimky
► V některých situacích je vhodné v rámci ošetření výjimky vyvolat
jinou výjimku, a přitom umožnit zjistit,
která výjimka byla prvotním hybatelem celé akce
► Řada výjimek má mezi svými konstruktory i takové,
které akceptují jako poslední parametr
odkaz na výjimku, jež byla příčinou vyvolání dané výjimky
► Chce-li se program zeptat výjimky na výjimku, která ji způsobila,
použije metodu
public Throwable getCause()
► Ve zprávě o vyvolání výjimky jsou místa, kde byla jedna výjimka
nahrazena jinou, označována textem caused by:
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
22
Ukázka výpisu při zřetězení výjimek
HighLevelException: MidLevelException: LowLevelException
at Junk.a(Junk.java:13)
at Junk.main(Junk.java:4)
Caused by: MidLevelException: LowLevelException
at Junk.c(Junk.java:23)
at Junk.b(Junk.java:17)
at Junk.a(Junk.java:11)
... 1 more
Caused by: LowLevelException
at Junk.e(Junk.java:30)
at Junk.d(Junk.java:27)
at Junk.c(Junk.java:21)
... 3 more
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
23
Převod kontrolovaných na nekontrolované
► Ošetřování kontrolovaných výjimek obtěžuje
► Víme-li, že k dané výjimce nejspíš nedojde
a ošetřujeme-li ji pouze proto, že na tom překladač trvá,
můžeme pro případ, že by k výjimce přece jenom došlo
zaměnit kontrolovanou výjimku za nekontrolovanou
public void prevod( String s ) {
try {
prověř( s );
} catch( Exception ex ) {
throw new RuntimeException( " Neprověřeno! ", ex );
}
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
24
Vaše jistota na trhu IT
Definice vlastních výjimek
►Hierarchie výjimek
►Pořadí výjimek v blocích catch
►Metody generující výjimky
►Metody třídy Throwable
►Vlastní výjimky
►Zásady správného používání výjimek
Definice vlastních výjimek
► Výjimky jsou zcela běžné třídy;
považujeme-li to proto za vhodné, můžeme definovat i vlastní
► Před definicí nové výjimky bychom si měli ujasnit,
bude-li kontrolovaná či nekontrolovaná;
podle toho definujeme jejího předka
► Název výjimek končí dle konvencí slovem Exception
před nímž je naznačena podstata dané výjimky
● IllegalArgumetnException
● NoSuchMethodException
● BadStringOperationException
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
26
Příklad vlastní kontrolované výjimky
public class VelkýPrůšvihException
extends Exception
{
public VelkýPrůšvihException() {};
public VelkýPrůšvihException( String zpráva ) {
super( zpráva );
}
public VelkýPrůšvihException(String zpráva,
Throwable původce ) {
super( zpráva, původce );
}
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
27
Test správného vyhození výjimky
► Na vytvářených programech je třeba otestovat i to,
že v definovaných situacích vyhodí požadovanou výjimku
public void testVyhozeníVýjimky()
{
try {
metodaKteráMáVyhoditVýjimku();
} catch ( VelkýPrůšvihException vpe ) {
return;
}
fail( "Nebyla vyhozena výjimka VelkýPrůšvihException" );
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
28
Zásady správného používání výjimek
1/2
Neignorujte
výjimky
try {
//Nějaký kód
}
catch(Exception e){}
► Výjimky, o nichž víte, že nemohou nastat,
převeďte na nekontrolované pro případ,
že by v budoucích verzích programu nastat mohly
► Při ošetřování výjimek, které nastat mohou,
ale nemají vliv na chod programu,
vložte do těla ošetření alespoň vysvětlující komentář
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
29
Zásady správného používání výjimek
2/2
► Používejte výjimky pouze k ošetření výjimečných stavů
► Kontrolované výjimky používejte u stavů, z nichž se lze zotavit,
jinak použijte výjimky nekontrolované
► Vyhýbejte se zbytečnému používání kontrolovaných výjimek
● Programátory ošetřování kontrolovaných výjimek obtěžuje
a mají pak tendenci je ošetřovat prázdným blokem catch
► Dávejte přednost standardním výjimkám,
vyvolávejte výjimky odpovídající dané abstrakci
● Programátoři by měli z názvu výjimky poznat, co se stalo
● Standardní výjimky mají všeobecně známý význam
► Snažte se o atomičnost selhání; i po vyhození výjimky
by měl být objekt v dobře definovaném stavu
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
30
Zásady správného používání výjimek
3/2
► Doplňujte výjimky zprávami,
výjimka by sama měla poskytnout dostatek informací
a neměla by programátora nutit k podrobnější analýze programu
► Dokumentujte vyvolávané výjimky v dokumentačních
komentářích pomocí značky @throws
► Nedělejte bloky try zbytečně velké,
kód uvnitř těchto bloků se neoptimalizuje
► Umíte-li výjimku v metodě ošetřit, udělejte to
► Detekuje-li se chyba v jedné metodě a má se ošetřit v jiné
(stejné či jiné instance), použijte výjimku.
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
31
Nejčastěji používané výjimky
1/2
► IllegalArgumentException
Byla zadána nepovolená hodnota parametru
● Např. chci nastavit zápornou velikost grafického tvaru
► IllegalStateException
V daném stavu objektu nelze metodu provést
● Např. otevřu soubor, přečtu pár vět, zavřu soubor a chci znovu přečíst větu
► NullPointerException
Byla vyvolána metoda instance, na níž ukazuje prázdný odkaz,
nebo byl předán nepovolený prázdný odkaz v parametru
► ArrayIndexOutOfBoundException
Byly zadány špatné meze pole, buď záporné nebo moc velké
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
32
Nejčastěji používané výjimky
2/2
► ConcurrentModificationException
V průběhu iterace byla změněna struktura kontejneru
● Např. byl do kontejneru přidán prvek
► NumberFormatException
Je požadován špatný převod řetězce na číslo či naopak
● Chci-li např. převést na číslo řetězec, který není číslem
● Častá chyba v metodách String.format či PrintStream.printf
► ClassCastException
Požadované přetypování není možné
► UnsupportedOperationException
Požadovaná operace není podporována
(např. chci přidat prvek do neměnného kontejneru)
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
33
Vaše jistota na trhu IT
Děkuji za pozornost
►Rudolf Pecinovský
http://vyuka.pecinovsky.cz/vse
mail: [email protected]
ICQ: 158 156 600
Slide 15
Vaše jistota na trhu IT
Výjimky
Rudolf Pecinovský
[email protected]
Vaše jistota na trhu IT
Obsah s odkazy
►Výjimky
►Výjimky kontrolované a nekontrolované
►Definice vlastních výjimek
Vaše jistota na trhu IT
Výjimky
►Výjimečné situace v programech
►Ošetření nestandardních situací v Javě
►Zpráva o výjimce
►Klíčová slova
►Činnost
►Vyvolání
Výjimečné situace v programech
► V každém programu je alespoň jedna chyba –
program na ni musí být připraven
► Starší programy
● Program vypsal chybové hlášení a ukončil činnost;
● V některých situacích (válcovací stolice, autopilot, …) nepřijatelné
● Funkce vrátí hodnotu signalizující chybu
● Programátor musí neustále testovat, co funkce vrací
● Knihovna měla pro tyto účely vyhrazenu speciální proměnnou,
do níž se v případě chyby zapsal její kód; nahlédnutím do proměnné
program zjistil kód poslední chyby
● Programátor musí neustále testovat, jaká je v proměnné hodnota
► Některé jazyky (Cobol, PL/1, …) proto přišly s koncepcí
ošetření nestandardních situací
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
4
Ošetření nestandardních situací v Javě
► Výjimečná událost =
problém, který brání dalšímu vykonávání části kódu
► Událost je výjimečná v tom, že na rozdíl od běžných problémů
nemá program k vyřešení situace dost informaci
► Program může při výskytu výjimečné události vyvolat výjimku
► Výjimka (exception)
objekt určený k přenosu informací o nastalém problému
z místa jeho vzniku do místa, kde bude problém řešen
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
5
Postup při vyvolání výjimky
1. Vytvoří se výjimka = objekt typu Throwable
(prakticky vždy instance některého z potomků)
2. Vytvořená výjimka se vyhodí =
přeruší se běh programu v místě, kde výjimka vznikla,
a začne se hledat místo, kde bude daná výjimka ošetřena
3. Ošetření výjimky (handler) by mělo uvést program do stavu,
v němž může jeho vykonávání pokračovat
► Výjimka „probublává“ programem z místa vyhození stále výše
a nenarazí-li cestou nikde na své ošetření,
zachytí ji virtuální stroj, který na standardní chybový výstup
vypíše zprávu o vzniku výjimky
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
6
Systémová zpráva o vzniku výjimky
Zpráva o vzniku výjimky spolu s názvem vlákna,
v němž k výjimce došlo (zde AWT-EventQueue-0)
Popis druhu výjimky (aritmetická výjimka dělení nulou)
Informace o místě, odkud byla volána metoda,
která vyvolala metodu, v níž došlo k vyhození výjimky
Informace o místě, odkud byla volána metoda,
v níž došlo k vyhození výjimky
Úplný název třídy včetně balíčku
Copyright © 2006, Rudolf Pecinovský
Název metody
VŠE – 05
Název souboru se
zdrojovým kódem
Číslo řádku zdrojáku,
kde došlo k výjimce
7
Klíčová slova související s výjimkami
► try (zkus)
Označuje blok kódu, v němž může dojít k výjimce
► throw (hoď)
Příkaz k vyhození výjimky;
musí být následován odkazem na existující instanci
► catch (chyť)
Blok ošetřující výjimku, která je zadána jako parametr
► finally (na konec)
Blok s povinnými závěrečnými akcemi nezávisejícími
na případném vzniku výjimky
► throws (hází)
Uvození seznamu výjimek vyhazovaných danou metodou
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
8
Vyvolání a ošetření výjimky v kódu
try {
//Kód, který může vyvolat výjimky
}
catch( Typ1 id1 ) {
//Ošetření výjimek typu Typ1
}
...
catch( TypN idN ) {
//ošetření výjimek typu TypN
}
finally {
//Kód, který se na závěr VŽDY provede
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
9
Náznak činnosti – řádný průběh
nedojde k vyvolání výjimky
= nedojde k chybě
try {
příkaz1();
příkaz2();
příkaz3();
}
catch ( xxxException e ) {
příkazProOšetřeníChyby();
}
Bloky catch
catch (…..
se přeskočí
finally {
ukončovacíPříkazy();
}
dalšíPříkaz();
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
12
Náznak činnosti – ošetřený výjimka
try {
příkaz1(); Při provádění metody příkaz2
dojde k ošetřené chybě
příkaz2();
příkaz3();
Byla vyhozena výjimka
tohoto typu nebo typu
}
některého z potomků
catch ( xxxException e ) {
příkazProOšetřeníChyby();
}
Ostatní bloky catch
catch (…..
se přeskočí
finally {
ukončovacíPříkazy();
}
dalšíPříkaz();
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
13
Náznak činnosti – neošetřená výjimka
Při provádění metody příkaz2
dojde k NEošetřené chybě
try {
příkaz1();
příkaz2();
příkaz3();
}
catch ( xxxException e ) {
příkazProOšetřeníChyby();
}
Ošetření nebylo nalezeno =>
catch (…..
provede se blok finally
a opouští se metoda
finally {
ukončovacíPříkazy();
}
dalšíPříkaz();
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
14
Vyvolání výjimky
public class Xyz implements Comparable
{
public bolean compareTo( Object o )
{
if( !(o instanceOf Xyz) )
throw new ClassCastException (
"\nPokus o porovnání s neporovnatelnou"
+ " instancí " + o );
//Zjištění, kdo je větší
return vysledek;
}
}
► Instanci nemusíme vytvářet až v příkazu throw,
můžeme ji vytvořit kdykoliv před tím a pak mu ji jen předat
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
15
Vaše jistota na trhu IT
Výjimky kontrolované a
nekontrolované
►Hierarchie výjimek
►Pořadí výjimek v blocích catch
►Metody generující výjimky
►Metody třídy Throwable
►Zřetězené výjimky
►Převod kontrolovaných na nekontrolované
Charakteristika
► Výjimky, které jsou potomky třídy RuntimeException
nebo Error označujeme jako nekontrolované (unchecked),
protože překladač nekontroluje, zda je na ně program připraven
► Ostatní výjimky označujeme jako kontrolované (checked),
protože překladač kontroluje dodržení pravidel:
● Každá metoda, která může vyhodit kontrolovanou výjimku,
se musí k této skutečnosti veřejně přihlásit
● Každé použití metody, která může vyhodit kontrolovanou výjimku,
musí být buď uzavřeno v bloku try…catch,
nebo se volající metoda musí přihlásit k tomu,
že může také vyhodit danou kontrolovanou výjimku
► Nekontrolované výjimky ohlašují chyby v programu,
kontrolované výjimky očekávatelné situace,
na jejichž výskyt má být program připraven
a měl by na ně umět reagovat
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
17
Hierarchie výjimek
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
18
Pořadí výjimek v blocích catch
► Třída NumberFormatException
je potomkem třídy RuntimeException
try {
Syntaktická chyba,
......
na druhý blok catch nikdy nedojde
}
catch (RuntimeException e) {
.........
}
Obrácené pořadí bloků catch
catch (NumberFormatException e){
vše vyřeší
........
try {
}
......
}
catch (NumberFormatException e) {
.........
}
catch (RuntimeException e){
........
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
19
Metody generující výjimky
► Java vyžaduje, aby programy, které používají metody
schopné vyvolat kontrolované výjimky,
byly o této schopnosti používaných metod informovány =>
pak vědí, které výjimku musí umět zachytit a ošetřit
► Všechny kontrolované výjimky, které může metoda vyhodit,
musí deklarovat v hlavičce za klíčovým slovem throws
► Deklarace vyhazování nekontrolovaných výjimek není povinná
public void metoda()
throws KontrolovanáVýjimka1,
KontrolovanáVýjimka2
{
// Tělo metody
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
20
Metody třídy Throwable
► String getMessage()
Vrátí zprávu popisující danou výjimku
► String toString()
Vrátí název třídy výjimky následovaný případnou zprávou
► void printStackTrace()
Vytiskne toString() následovaný sadou informací o volající
posloupnosti, která vedla k vzniku výjimky
► Throwable fillInStackTrace()
Připraví nové informace o volací posloupnosti
vedoucí k místu zavolání této metody
► StackTraceElement[] getStackTrace()
Vrátí uchované informace o volací posloupnosti dané výjimky
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
21
Zřetězené výjimky
► V některých situacích je vhodné v rámci ošetření výjimky vyvolat
jinou výjimku, a přitom umožnit zjistit,
která výjimka byla prvotním hybatelem celé akce
► Řada výjimek má mezi svými konstruktory i takové,
které akceptují jako poslední parametr
odkaz na výjimku, jež byla příčinou vyvolání dané výjimky
► Chce-li se program zeptat výjimky na výjimku, která ji způsobila,
použije metodu
public Throwable getCause()
► Ve zprávě o vyvolání výjimky jsou místa, kde byla jedna výjimka
nahrazena jinou, označována textem caused by:
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
22
Ukázka výpisu při zřetězení výjimek
HighLevelException: MidLevelException: LowLevelException
at Junk.a(Junk.java:13)
at Junk.main(Junk.java:4)
Caused by: MidLevelException: LowLevelException
at Junk.c(Junk.java:23)
at Junk.b(Junk.java:17)
at Junk.a(Junk.java:11)
... 1 more
Caused by: LowLevelException
at Junk.e(Junk.java:30)
at Junk.d(Junk.java:27)
at Junk.c(Junk.java:21)
... 3 more
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
23
Převod kontrolovaných na nekontrolované
► Ošetřování kontrolovaných výjimek obtěžuje
► Víme-li, že k dané výjimce nejspíš nedojde
a ošetřujeme-li ji pouze proto, že na tom překladač trvá,
můžeme pro případ, že by k výjimce přece jenom došlo
zaměnit kontrolovanou výjimku za nekontrolovanou
public void prevod( String s ) {
try {
prověř( s );
} catch( Exception ex ) {
throw new RuntimeException( " Neprověřeno! ", ex );
}
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
24
Vaše jistota na trhu IT
Definice vlastních výjimek
►Hierarchie výjimek
►Pořadí výjimek v blocích catch
►Metody generující výjimky
►Metody třídy Throwable
►Vlastní výjimky
►Zásady správného používání výjimek
Definice vlastních výjimek
► Výjimky jsou zcela běžné třídy;
považujeme-li to proto za vhodné, můžeme definovat i vlastní
► Před definicí nové výjimky bychom si měli ujasnit,
bude-li kontrolovaná či nekontrolovaná;
podle toho definujeme jejího předka
► Název výjimek končí dle konvencí slovem Exception
před nímž je naznačena podstata dané výjimky
● IllegalArgumetnException
● NoSuchMethodException
● BadStringOperationException
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
26
Příklad vlastní kontrolované výjimky
public class VelkýPrůšvihException
extends Exception
{
public VelkýPrůšvihException() {};
public VelkýPrůšvihException( String zpráva ) {
super( zpráva );
}
public VelkýPrůšvihException(String zpráva,
Throwable původce ) {
super( zpráva, původce );
}
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
27
Test správného vyhození výjimky
► Na vytvářených programech je třeba otestovat i to,
že v definovaných situacích vyhodí požadovanou výjimku
public void testVyhozeníVýjimky()
{
try {
metodaKteráMáVyhoditVýjimku();
} catch ( VelkýPrůšvihException vpe ) {
return;
}
fail( "Nebyla vyhozena výjimka VelkýPrůšvihException" );
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
28
Zásady správného používání výjimek
1/2
Neignorujte
výjimky
try {
//Nějaký kód
}
catch(Exception e){}
► Výjimky, o nichž víte, že nemohou nastat,
převeďte na nekontrolované pro případ,
že by v budoucích verzích programu nastat mohly
► Při ošetřování výjimek, které nastat mohou,
ale nemají vliv na chod programu,
vložte do těla ošetření alespoň vysvětlující komentář
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
29
Zásady správného používání výjimek
2/2
► Používejte výjimky pouze k ošetření výjimečných stavů
► Kontrolované výjimky používejte u stavů, z nichž se lze zotavit,
jinak použijte výjimky nekontrolované
► Vyhýbejte se zbytečnému používání kontrolovaných výjimek
● Programátory ošetřování kontrolovaných výjimek obtěžuje
a mají pak tendenci je ošetřovat prázdným blokem catch
► Dávejte přednost standardním výjimkám,
vyvolávejte výjimky odpovídající dané abstrakci
● Programátoři by měli z názvu výjimky poznat, co se stalo
● Standardní výjimky mají všeobecně známý význam
► Snažte se o atomičnost selhání; i po vyhození výjimky
by měl být objekt v dobře definovaném stavu
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
30
Zásady správného používání výjimek
3/2
► Doplňujte výjimky zprávami,
výjimka by sama měla poskytnout dostatek informací
a neměla by programátora nutit k podrobnější analýze programu
► Dokumentujte vyvolávané výjimky v dokumentačních
komentářích pomocí značky @throws
► Nedělejte bloky try zbytečně velké,
kód uvnitř těchto bloků se neoptimalizuje
► Umíte-li výjimku v metodě ošetřit, udělejte to
► Detekuje-li se chyba v jedné metodě a má se ošetřit v jiné
(stejné či jiné instance), použijte výjimku.
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
31
Nejčastěji používané výjimky
1/2
► IllegalArgumentException
Byla zadána nepovolená hodnota parametru
● Např. chci nastavit zápornou velikost grafického tvaru
► IllegalStateException
V daném stavu objektu nelze metodu provést
● Např. otevřu soubor, přečtu pár vět, zavřu soubor a chci znovu přečíst větu
► NullPointerException
Byla vyvolána metoda instance, na níž ukazuje prázdný odkaz,
nebo byl předán nepovolený prázdný odkaz v parametru
► ArrayIndexOutOfBoundException
Byly zadány špatné meze pole, buď záporné nebo moc velké
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
32
Nejčastěji používané výjimky
2/2
► ConcurrentModificationException
V průběhu iterace byla změněna struktura kontejneru
● Např. byl do kontejneru přidán prvek
► NumberFormatException
Je požadován špatný převod řetězce na číslo či naopak
● Chci-li např. převést na číslo řetězec, který není číslem
● Častá chyba v metodách String.format či PrintStream.printf
► ClassCastException
Požadované přetypování není možné
► UnsupportedOperationException
Požadovaná operace není podporována
(např. chci přidat prvek do neměnného kontejneru)
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
33
Vaše jistota na trhu IT
Děkuji za pozornost
►Rudolf Pecinovský
http://vyuka.pecinovsky.cz/vse
mail: [email protected]
ICQ: 158 156 600
Slide 16
Vaše jistota na trhu IT
Výjimky
Rudolf Pecinovský
[email protected]
Vaše jistota na trhu IT
Obsah s odkazy
►Výjimky
►Výjimky kontrolované a nekontrolované
►Definice vlastních výjimek
Vaše jistota na trhu IT
Výjimky
►Výjimečné situace v programech
►Ošetření nestandardních situací v Javě
►Zpráva o výjimce
►Klíčová slova
►Činnost
►Vyvolání
Výjimečné situace v programech
► V každém programu je alespoň jedna chyba –
program na ni musí být připraven
► Starší programy
● Program vypsal chybové hlášení a ukončil činnost;
● V některých situacích (válcovací stolice, autopilot, …) nepřijatelné
● Funkce vrátí hodnotu signalizující chybu
● Programátor musí neustále testovat, co funkce vrací
● Knihovna měla pro tyto účely vyhrazenu speciální proměnnou,
do níž se v případě chyby zapsal její kód; nahlédnutím do proměnné
program zjistil kód poslední chyby
● Programátor musí neustále testovat, jaká je v proměnné hodnota
► Některé jazyky (Cobol, PL/1, …) proto přišly s koncepcí
ošetření nestandardních situací
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
4
Ošetření nestandardních situací v Javě
► Výjimečná událost =
problém, který brání dalšímu vykonávání části kódu
► Událost je výjimečná v tom, že na rozdíl od běžných problémů
nemá program k vyřešení situace dost informaci
► Program může při výskytu výjimečné události vyvolat výjimku
► Výjimka (exception)
objekt určený k přenosu informací o nastalém problému
z místa jeho vzniku do místa, kde bude problém řešen
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
5
Postup při vyvolání výjimky
1. Vytvoří se výjimka = objekt typu Throwable
(prakticky vždy instance některého z potomků)
2. Vytvořená výjimka se vyhodí =
přeruší se běh programu v místě, kde výjimka vznikla,
a začne se hledat místo, kde bude daná výjimka ošetřena
3. Ošetření výjimky (handler) by mělo uvést program do stavu,
v němž může jeho vykonávání pokračovat
► Výjimka „probublává“ programem z místa vyhození stále výše
a nenarazí-li cestou nikde na své ošetření,
zachytí ji virtuální stroj, který na standardní chybový výstup
vypíše zprávu o vzniku výjimky
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
6
Systémová zpráva o vzniku výjimky
Zpráva o vzniku výjimky spolu s názvem vlákna,
v němž k výjimce došlo (zde AWT-EventQueue-0)
Popis druhu výjimky (aritmetická výjimka dělení nulou)
Informace o místě, odkud byla volána metoda,
která vyvolala metodu, v níž došlo k vyhození výjimky
Informace o místě, odkud byla volána metoda,
v níž došlo k vyhození výjimky
Úplný název třídy včetně balíčku
Copyright © 2006, Rudolf Pecinovský
Název metody
VŠE – 05
Název souboru se
zdrojovým kódem
Číslo řádku zdrojáku,
kde došlo k výjimce
7
Klíčová slova související s výjimkami
► try (zkus)
Označuje blok kódu, v němž může dojít k výjimce
► throw (hoď)
Příkaz k vyhození výjimky;
musí být následován odkazem na existující instanci
► catch (chyť)
Blok ošetřující výjimku, která je zadána jako parametr
► finally (na konec)
Blok s povinnými závěrečnými akcemi nezávisejícími
na případném vzniku výjimky
► throws (hází)
Uvození seznamu výjimek vyhazovaných danou metodou
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
8
Vyvolání a ošetření výjimky v kódu
try {
//Kód, který může vyvolat výjimky
}
catch( Typ1 id1 ) {
//Ošetření výjimek typu Typ1
}
...
catch( TypN idN ) {
//ošetření výjimek typu TypN
}
finally {
//Kód, který se na závěr VŽDY provede
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
9
Náznak činnosti – řádný průběh
nedojde k vyvolání výjimky
= nedojde k chybě
try {
příkaz1();
příkaz2();
příkaz3();
}
catch ( xxxException e ) {
příkazProOšetřeníChyby();
}
Bloky catch
catch (…..
se přeskočí
finally {
ukončovacíPříkazy();
}
dalšíPříkaz();
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
12
Náznak činnosti – ošetřený výjimka
try {
příkaz1(); Při provádění metody příkaz2
dojde k ošetřené chybě
příkaz2();
příkaz3();
Byla vyhozena výjimka
tohoto typu nebo typu
}
některého z potomků
catch ( xxxException e ) {
příkazProOšetřeníChyby();
}
Ostatní bloky catch
catch (…..
se přeskočí
finally {
ukončovacíPříkazy();
}
dalšíPříkaz();
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
13
Náznak činnosti – neošetřená výjimka
Při provádění metody příkaz2
dojde k NEošetřené chybě
try {
příkaz1();
příkaz2();
příkaz3();
}
catch ( xxxException e ) {
příkazProOšetřeníChyby();
}
Ošetření nebylo nalezeno =>
catch (…..
provede se blok finally
a opouští se metoda
finally {
ukončovacíPříkazy();
}
dalšíPříkaz();
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
14
Vyvolání výjimky
public class Xyz implements Comparable
{
public bolean compareTo( Object o )
{
if( !(o instanceOf Xyz) )
throw new ClassCastException (
"\nPokus o porovnání s neporovnatelnou"
+ " instancí " + o );
//Zjištění, kdo je větší
return vysledek;
}
}
► Instanci nemusíme vytvářet až v příkazu throw,
můžeme ji vytvořit kdykoliv před tím a pak mu ji jen předat
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
15
Vaše jistota na trhu IT
Výjimky kontrolované a
nekontrolované
►Hierarchie výjimek
►Pořadí výjimek v blocích catch
►Metody generující výjimky
►Metody třídy Throwable
►Zřetězené výjimky
►Převod kontrolovaných na nekontrolované
Charakteristika
► Výjimky, které jsou potomky třídy RuntimeException
nebo Error označujeme jako nekontrolované (unchecked),
protože překladač nekontroluje, zda je na ně program připraven
► Ostatní výjimky označujeme jako kontrolované (checked),
protože překladač kontroluje dodržení pravidel:
● Každá metoda, která může vyhodit kontrolovanou výjimku,
se musí k této skutečnosti veřejně přihlásit
● Každé použití metody, která může vyhodit kontrolovanou výjimku,
musí být buď uzavřeno v bloku try…catch,
nebo se volající metoda musí přihlásit k tomu,
že může také vyhodit danou kontrolovanou výjimku
► Nekontrolované výjimky ohlašují chyby v programu,
kontrolované výjimky očekávatelné situace,
na jejichž výskyt má být program připraven
a měl by na ně umět reagovat
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
17
Hierarchie výjimek
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
18
Pořadí výjimek v blocích catch
► Třída NumberFormatException
je potomkem třídy RuntimeException
try {
Syntaktická chyba,
......
na druhý blok catch nikdy nedojde
}
catch (RuntimeException e) {
.........
}
Obrácené pořadí bloků catch
catch (NumberFormatException e){
vše vyřeší
........
try {
}
......
}
catch (NumberFormatException e) {
.........
}
catch (RuntimeException e){
........
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
19
Metody generující výjimky
► Java vyžaduje, aby programy, které používají metody
schopné vyvolat kontrolované výjimky,
byly o této schopnosti používaných metod informovány =>
pak vědí, které výjimku musí umět zachytit a ošetřit
► Všechny kontrolované výjimky, které může metoda vyhodit,
musí deklarovat v hlavičce za klíčovým slovem throws
► Deklarace vyhazování nekontrolovaných výjimek není povinná
public void metoda()
throws KontrolovanáVýjimka1,
KontrolovanáVýjimka2
{
// Tělo metody
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
20
Metody třídy Throwable
► String getMessage()
Vrátí zprávu popisující danou výjimku
► String toString()
Vrátí název třídy výjimky následovaný případnou zprávou
► void printStackTrace()
Vytiskne toString() následovaný sadou informací o volající
posloupnosti, která vedla k vzniku výjimky
► Throwable fillInStackTrace()
Připraví nové informace o volací posloupnosti
vedoucí k místu zavolání této metody
► StackTraceElement[] getStackTrace()
Vrátí uchované informace o volací posloupnosti dané výjimky
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
21
Zřetězené výjimky
► V některých situacích je vhodné v rámci ošetření výjimky vyvolat
jinou výjimku, a přitom umožnit zjistit,
která výjimka byla prvotním hybatelem celé akce
► Řada výjimek má mezi svými konstruktory i takové,
které akceptují jako poslední parametr
odkaz na výjimku, jež byla příčinou vyvolání dané výjimky
► Chce-li se program zeptat výjimky na výjimku, která ji způsobila,
použije metodu
public Throwable getCause()
► Ve zprávě o vyvolání výjimky jsou místa, kde byla jedna výjimka
nahrazena jinou, označována textem caused by:
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
22
Ukázka výpisu při zřetězení výjimek
HighLevelException: MidLevelException: LowLevelException
at Junk.a(Junk.java:13)
at Junk.main(Junk.java:4)
Caused by: MidLevelException: LowLevelException
at Junk.c(Junk.java:23)
at Junk.b(Junk.java:17)
at Junk.a(Junk.java:11)
... 1 more
Caused by: LowLevelException
at Junk.e(Junk.java:30)
at Junk.d(Junk.java:27)
at Junk.c(Junk.java:21)
... 3 more
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
23
Převod kontrolovaných na nekontrolované
► Ošetřování kontrolovaných výjimek obtěžuje
► Víme-li, že k dané výjimce nejspíš nedojde
a ošetřujeme-li ji pouze proto, že na tom překladač trvá,
můžeme pro případ, že by k výjimce přece jenom došlo
zaměnit kontrolovanou výjimku za nekontrolovanou
public void prevod( String s ) {
try {
prověř( s );
} catch( Exception ex ) {
throw new RuntimeException( " Neprověřeno! ", ex );
}
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
24
Vaše jistota na trhu IT
Definice vlastních výjimek
►Hierarchie výjimek
►Pořadí výjimek v blocích catch
►Metody generující výjimky
►Metody třídy Throwable
►Vlastní výjimky
►Zásady správného používání výjimek
Definice vlastních výjimek
► Výjimky jsou zcela běžné třídy;
považujeme-li to proto za vhodné, můžeme definovat i vlastní
► Před definicí nové výjimky bychom si měli ujasnit,
bude-li kontrolovaná či nekontrolovaná;
podle toho definujeme jejího předka
► Název výjimek končí dle konvencí slovem Exception
před nímž je naznačena podstata dané výjimky
● IllegalArgumetnException
● NoSuchMethodException
● BadStringOperationException
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
26
Příklad vlastní kontrolované výjimky
public class VelkýPrůšvihException
extends Exception
{
public VelkýPrůšvihException() {};
public VelkýPrůšvihException( String zpráva ) {
super( zpráva );
}
public VelkýPrůšvihException(String zpráva,
Throwable původce ) {
super( zpráva, původce );
}
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
27
Test správného vyhození výjimky
► Na vytvářených programech je třeba otestovat i to,
že v definovaných situacích vyhodí požadovanou výjimku
public void testVyhozeníVýjimky()
{
try {
metodaKteráMáVyhoditVýjimku();
} catch ( VelkýPrůšvihException vpe ) {
return;
}
fail( "Nebyla vyhozena výjimka VelkýPrůšvihException" );
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
28
Zásady správného používání výjimek
1/2
Neignorujte
výjimky
try {
//Nějaký kód
}
catch(Exception e){}
► Výjimky, o nichž víte, že nemohou nastat,
převeďte na nekontrolované pro případ,
že by v budoucích verzích programu nastat mohly
► Při ošetřování výjimek, které nastat mohou,
ale nemají vliv na chod programu,
vložte do těla ošetření alespoň vysvětlující komentář
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
29
Zásady správného používání výjimek
2/2
► Používejte výjimky pouze k ošetření výjimečných stavů
► Kontrolované výjimky používejte u stavů, z nichž se lze zotavit,
jinak použijte výjimky nekontrolované
► Vyhýbejte se zbytečnému používání kontrolovaných výjimek
● Programátory ošetřování kontrolovaných výjimek obtěžuje
a mají pak tendenci je ošetřovat prázdným blokem catch
► Dávejte přednost standardním výjimkám,
vyvolávejte výjimky odpovídající dané abstrakci
● Programátoři by měli z názvu výjimky poznat, co se stalo
● Standardní výjimky mají všeobecně známý význam
► Snažte se o atomičnost selhání; i po vyhození výjimky
by měl být objekt v dobře definovaném stavu
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
30
Zásady správného používání výjimek
3/2
► Doplňujte výjimky zprávami,
výjimka by sama měla poskytnout dostatek informací
a neměla by programátora nutit k podrobnější analýze programu
► Dokumentujte vyvolávané výjimky v dokumentačních
komentářích pomocí značky @throws
► Nedělejte bloky try zbytečně velké,
kód uvnitř těchto bloků se neoptimalizuje
► Umíte-li výjimku v metodě ošetřit, udělejte to
► Detekuje-li se chyba v jedné metodě a má se ošetřit v jiné
(stejné či jiné instance), použijte výjimku.
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
31
Nejčastěji používané výjimky
1/2
► IllegalArgumentException
Byla zadána nepovolená hodnota parametru
● Např. chci nastavit zápornou velikost grafického tvaru
► IllegalStateException
V daném stavu objektu nelze metodu provést
● Např. otevřu soubor, přečtu pár vět, zavřu soubor a chci znovu přečíst větu
► NullPointerException
Byla vyvolána metoda instance, na níž ukazuje prázdný odkaz,
nebo byl předán nepovolený prázdný odkaz v parametru
► ArrayIndexOutOfBoundException
Byly zadány špatné meze pole, buď záporné nebo moc velké
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
32
Nejčastěji používané výjimky
2/2
► ConcurrentModificationException
V průběhu iterace byla změněna struktura kontejneru
● Např. byl do kontejneru přidán prvek
► NumberFormatException
Je požadován špatný převod řetězce na číslo či naopak
● Chci-li např. převést na číslo řetězec, který není číslem
● Častá chyba v metodách String.format či PrintStream.printf
► ClassCastException
Požadované přetypování není možné
► UnsupportedOperationException
Požadovaná operace není podporována
(např. chci přidat prvek do neměnného kontejneru)
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
33
Vaše jistota na trhu IT
Děkuji za pozornost
►Rudolf Pecinovský
http://vyuka.pecinovsky.cz/vse
mail: [email protected]
ICQ: 158 156 600
Slide 17
Vaše jistota na trhu IT
Výjimky
Rudolf Pecinovský
[email protected]
Vaše jistota na trhu IT
Obsah s odkazy
►Výjimky
►Výjimky kontrolované a nekontrolované
►Definice vlastních výjimek
Vaše jistota na trhu IT
Výjimky
►Výjimečné situace v programech
►Ošetření nestandardních situací v Javě
►Zpráva o výjimce
►Klíčová slova
►Činnost
►Vyvolání
Výjimečné situace v programech
► V každém programu je alespoň jedna chyba –
program na ni musí být připraven
► Starší programy
● Program vypsal chybové hlášení a ukončil činnost;
● V některých situacích (válcovací stolice, autopilot, …) nepřijatelné
● Funkce vrátí hodnotu signalizující chybu
● Programátor musí neustále testovat, co funkce vrací
● Knihovna měla pro tyto účely vyhrazenu speciální proměnnou,
do níž se v případě chyby zapsal její kód; nahlédnutím do proměnné
program zjistil kód poslední chyby
● Programátor musí neustále testovat, jaká je v proměnné hodnota
► Některé jazyky (Cobol, PL/1, …) proto přišly s koncepcí
ošetření nestandardních situací
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
4
Ošetření nestandardních situací v Javě
► Výjimečná událost =
problém, který brání dalšímu vykonávání části kódu
► Událost je výjimečná v tom, že na rozdíl od běžných problémů
nemá program k vyřešení situace dost informaci
► Program může při výskytu výjimečné události vyvolat výjimku
► Výjimka (exception)
objekt určený k přenosu informací o nastalém problému
z místa jeho vzniku do místa, kde bude problém řešen
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
5
Postup při vyvolání výjimky
1. Vytvoří se výjimka = objekt typu Throwable
(prakticky vždy instance některého z potomků)
2. Vytvořená výjimka se vyhodí =
přeruší se běh programu v místě, kde výjimka vznikla,
a začne se hledat místo, kde bude daná výjimka ošetřena
3. Ošetření výjimky (handler) by mělo uvést program do stavu,
v němž může jeho vykonávání pokračovat
► Výjimka „probublává“ programem z místa vyhození stále výše
a nenarazí-li cestou nikde na své ošetření,
zachytí ji virtuální stroj, který na standardní chybový výstup
vypíše zprávu o vzniku výjimky
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
6
Systémová zpráva o vzniku výjimky
Zpráva o vzniku výjimky spolu s názvem vlákna,
v němž k výjimce došlo (zde AWT-EventQueue-0)
Popis druhu výjimky (aritmetická výjimka dělení nulou)
Informace o místě, odkud byla volána metoda,
která vyvolala metodu, v níž došlo k vyhození výjimky
Informace o místě, odkud byla volána metoda,
v níž došlo k vyhození výjimky
Úplný název třídy včetně balíčku
Copyright © 2006, Rudolf Pecinovský
Název metody
VŠE – 05
Název souboru se
zdrojovým kódem
Číslo řádku zdrojáku,
kde došlo k výjimce
7
Klíčová slova související s výjimkami
► try (zkus)
Označuje blok kódu, v němž může dojít k výjimce
► throw (hoď)
Příkaz k vyhození výjimky;
musí být následován odkazem na existující instanci
► catch (chyť)
Blok ošetřující výjimku, která je zadána jako parametr
► finally (na konec)
Blok s povinnými závěrečnými akcemi nezávisejícími
na případném vzniku výjimky
► throws (hází)
Uvození seznamu výjimek vyhazovaných danou metodou
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
8
Vyvolání a ošetření výjimky v kódu
try {
//Kód, který může vyvolat výjimky
}
catch( Typ1 id1 ) {
//Ošetření výjimek typu Typ1
}
...
catch( TypN idN ) {
//ošetření výjimek typu TypN
}
finally {
//Kód, který se na závěr VŽDY provede
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
9
Náznak činnosti – řádný průběh
nedojde k vyvolání výjimky
= nedojde k chybě
try {
příkaz1();
příkaz2();
příkaz3();
}
catch ( xxxException e ) {
příkazProOšetřeníChyby();
}
Bloky catch
catch (…..
se přeskočí
finally {
ukončovacíPříkazy();
}
dalšíPříkaz();
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
12
Náznak činnosti – ošetřený výjimka
try {
příkaz1(); Při provádění metody příkaz2
dojde k ošetřené chybě
příkaz2();
příkaz3();
Byla vyhozena výjimka
tohoto typu nebo typu
}
některého z potomků
catch ( xxxException e ) {
příkazProOšetřeníChyby();
}
Ostatní bloky catch
catch (…..
se přeskočí
finally {
ukončovacíPříkazy();
}
dalšíPříkaz();
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
13
Náznak činnosti – neošetřená výjimka
Při provádění metody příkaz2
dojde k NEošetřené chybě
try {
příkaz1();
příkaz2();
příkaz3();
}
catch ( xxxException e ) {
příkazProOšetřeníChyby();
}
Ošetření nebylo nalezeno =>
catch (…..
provede se blok finally
a opouští se metoda
finally {
ukončovacíPříkazy();
}
dalšíPříkaz();
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
14
Vyvolání výjimky
public class Xyz implements Comparable
{
public bolean compareTo( Object o )
{
if( !(o instanceOf Xyz) )
throw new ClassCastException (
"\nPokus o porovnání s neporovnatelnou"
+ " instancí " + o );
//Zjištění, kdo je větší
return vysledek;
}
}
► Instanci nemusíme vytvářet až v příkazu throw,
můžeme ji vytvořit kdykoliv před tím a pak mu ji jen předat
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
15
Vaše jistota na trhu IT
Výjimky kontrolované a
nekontrolované
►Hierarchie výjimek
►Pořadí výjimek v blocích catch
►Metody generující výjimky
►Metody třídy Throwable
►Zřetězené výjimky
►Převod kontrolovaných na nekontrolované
Charakteristika
► Výjimky, které jsou potomky třídy RuntimeException
nebo Error označujeme jako nekontrolované (unchecked),
protože překladač nekontroluje, zda je na ně program připraven
► Ostatní výjimky označujeme jako kontrolované (checked),
protože překladač kontroluje dodržení pravidel:
● Každá metoda, která může vyhodit kontrolovanou výjimku,
se musí k této skutečnosti veřejně přihlásit
● Každé použití metody, která může vyhodit kontrolovanou výjimku,
musí být buď uzavřeno v bloku try…catch,
nebo se volající metoda musí přihlásit k tomu,
že může také vyhodit danou kontrolovanou výjimku
► Nekontrolované výjimky ohlašují chyby v programu,
kontrolované výjimky očekávatelné situace,
na jejichž výskyt má být program připraven
a měl by na ně umět reagovat
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
17
Hierarchie výjimek
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
18
Pořadí výjimek v blocích catch
► Třída NumberFormatException
je potomkem třídy RuntimeException
try {
Syntaktická chyba,
......
na druhý blok catch nikdy nedojde
}
catch (RuntimeException e) {
.........
}
Obrácené pořadí bloků catch
catch (NumberFormatException e){
vše vyřeší
........
try {
}
......
}
catch (NumberFormatException e) {
.........
}
catch (RuntimeException e){
........
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
19
Metody generující výjimky
► Java vyžaduje, aby programy, které používají metody
schopné vyvolat kontrolované výjimky,
byly o této schopnosti používaných metod informovány =>
pak vědí, které výjimku musí umět zachytit a ošetřit
► Všechny kontrolované výjimky, které může metoda vyhodit,
musí deklarovat v hlavičce za klíčovým slovem throws
► Deklarace vyhazování nekontrolovaných výjimek není povinná
public void metoda()
throws KontrolovanáVýjimka1,
KontrolovanáVýjimka2
{
// Tělo metody
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
20
Metody třídy Throwable
► String getMessage()
Vrátí zprávu popisující danou výjimku
► String toString()
Vrátí název třídy výjimky následovaný případnou zprávou
► void printStackTrace()
Vytiskne toString() následovaný sadou informací o volající
posloupnosti, která vedla k vzniku výjimky
► Throwable fillInStackTrace()
Připraví nové informace o volací posloupnosti
vedoucí k místu zavolání této metody
► StackTraceElement[] getStackTrace()
Vrátí uchované informace o volací posloupnosti dané výjimky
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
21
Zřetězené výjimky
► V některých situacích je vhodné v rámci ošetření výjimky vyvolat
jinou výjimku, a přitom umožnit zjistit,
která výjimka byla prvotním hybatelem celé akce
► Řada výjimek má mezi svými konstruktory i takové,
které akceptují jako poslední parametr
odkaz na výjimku, jež byla příčinou vyvolání dané výjimky
► Chce-li se program zeptat výjimky na výjimku, která ji způsobila,
použije metodu
public Throwable getCause()
► Ve zprávě o vyvolání výjimky jsou místa, kde byla jedna výjimka
nahrazena jinou, označována textem caused by:
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
22
Ukázka výpisu při zřetězení výjimek
HighLevelException: MidLevelException: LowLevelException
at Junk.a(Junk.java:13)
at Junk.main(Junk.java:4)
Caused by: MidLevelException: LowLevelException
at Junk.c(Junk.java:23)
at Junk.b(Junk.java:17)
at Junk.a(Junk.java:11)
... 1 more
Caused by: LowLevelException
at Junk.e(Junk.java:30)
at Junk.d(Junk.java:27)
at Junk.c(Junk.java:21)
... 3 more
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
23
Převod kontrolovaných na nekontrolované
► Ošetřování kontrolovaných výjimek obtěžuje
► Víme-li, že k dané výjimce nejspíš nedojde
a ošetřujeme-li ji pouze proto, že na tom překladač trvá,
můžeme pro případ, že by k výjimce přece jenom došlo
zaměnit kontrolovanou výjimku za nekontrolovanou
public void prevod( String s ) {
try {
prověř( s );
} catch( Exception ex ) {
throw new RuntimeException( " Neprověřeno! ", ex );
}
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
24
Vaše jistota na trhu IT
Definice vlastních výjimek
►Hierarchie výjimek
►Pořadí výjimek v blocích catch
►Metody generující výjimky
►Metody třídy Throwable
►Vlastní výjimky
►Zásady správného používání výjimek
Definice vlastních výjimek
► Výjimky jsou zcela běžné třídy;
považujeme-li to proto za vhodné, můžeme definovat i vlastní
► Před definicí nové výjimky bychom si měli ujasnit,
bude-li kontrolovaná či nekontrolovaná;
podle toho definujeme jejího předka
► Název výjimek končí dle konvencí slovem Exception
před nímž je naznačena podstata dané výjimky
● IllegalArgumetnException
● NoSuchMethodException
● BadStringOperationException
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
26
Příklad vlastní kontrolované výjimky
public class VelkýPrůšvihException
extends Exception
{
public VelkýPrůšvihException() {};
public VelkýPrůšvihException( String zpráva ) {
super( zpráva );
}
public VelkýPrůšvihException(String zpráva,
Throwable původce ) {
super( zpráva, původce );
}
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
27
Test správného vyhození výjimky
► Na vytvářených programech je třeba otestovat i to,
že v definovaných situacích vyhodí požadovanou výjimku
public void testVyhozeníVýjimky()
{
try {
metodaKteráMáVyhoditVýjimku();
} catch ( VelkýPrůšvihException vpe ) {
return;
}
fail( "Nebyla vyhozena výjimka VelkýPrůšvihException" );
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
28
Zásady správného používání výjimek
1/2
Neignorujte
výjimky
try {
//Nějaký kód
}
catch(Exception e){}
► Výjimky, o nichž víte, že nemohou nastat,
převeďte na nekontrolované pro případ,
že by v budoucích verzích programu nastat mohly
► Při ošetřování výjimek, které nastat mohou,
ale nemají vliv na chod programu,
vložte do těla ošetření alespoň vysvětlující komentář
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
29
Zásady správného používání výjimek
2/2
► Používejte výjimky pouze k ošetření výjimečných stavů
► Kontrolované výjimky používejte u stavů, z nichž se lze zotavit,
jinak použijte výjimky nekontrolované
► Vyhýbejte se zbytečnému používání kontrolovaných výjimek
● Programátory ošetřování kontrolovaných výjimek obtěžuje
a mají pak tendenci je ošetřovat prázdným blokem catch
► Dávejte přednost standardním výjimkám,
vyvolávejte výjimky odpovídající dané abstrakci
● Programátoři by měli z názvu výjimky poznat, co se stalo
● Standardní výjimky mají všeobecně známý význam
► Snažte se o atomičnost selhání; i po vyhození výjimky
by měl být objekt v dobře definovaném stavu
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
30
Zásady správného používání výjimek
3/2
► Doplňujte výjimky zprávami,
výjimka by sama měla poskytnout dostatek informací
a neměla by programátora nutit k podrobnější analýze programu
► Dokumentujte vyvolávané výjimky v dokumentačních
komentářích pomocí značky @throws
► Nedělejte bloky try zbytečně velké,
kód uvnitř těchto bloků se neoptimalizuje
► Umíte-li výjimku v metodě ošetřit, udělejte to
► Detekuje-li se chyba v jedné metodě a má se ošetřit v jiné
(stejné či jiné instance), použijte výjimku.
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
31
Nejčastěji používané výjimky
1/2
► IllegalArgumentException
Byla zadána nepovolená hodnota parametru
● Např. chci nastavit zápornou velikost grafického tvaru
► IllegalStateException
V daném stavu objektu nelze metodu provést
● Např. otevřu soubor, přečtu pár vět, zavřu soubor a chci znovu přečíst větu
► NullPointerException
Byla vyvolána metoda instance, na níž ukazuje prázdný odkaz,
nebo byl předán nepovolený prázdný odkaz v parametru
► ArrayIndexOutOfBoundException
Byly zadány špatné meze pole, buď záporné nebo moc velké
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
32
Nejčastěji používané výjimky
2/2
► ConcurrentModificationException
V průběhu iterace byla změněna struktura kontejneru
● Např. byl do kontejneru přidán prvek
► NumberFormatException
Je požadován špatný převod řetězce na číslo či naopak
● Chci-li např. převést na číslo řetězec, který není číslem
● Častá chyba v metodách String.format či PrintStream.printf
► ClassCastException
Požadované přetypování není možné
► UnsupportedOperationException
Požadovaná operace není podporována
(např. chci přidat prvek do neměnného kontejneru)
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
33
Vaše jistota na trhu IT
Děkuji za pozornost
►Rudolf Pecinovský
http://vyuka.pecinovsky.cz/vse
mail: [email protected]
ICQ: 158 156 600
Slide 18
Vaše jistota na trhu IT
Výjimky
Rudolf Pecinovský
[email protected]
Vaše jistota na trhu IT
Obsah s odkazy
►Výjimky
►Výjimky kontrolované a nekontrolované
►Definice vlastních výjimek
Vaše jistota na trhu IT
Výjimky
►Výjimečné situace v programech
►Ošetření nestandardních situací v Javě
►Zpráva o výjimce
►Klíčová slova
►Činnost
►Vyvolání
Výjimečné situace v programech
► V každém programu je alespoň jedna chyba –
program na ni musí být připraven
► Starší programy
● Program vypsal chybové hlášení a ukončil činnost;
● V některých situacích (válcovací stolice, autopilot, …) nepřijatelné
● Funkce vrátí hodnotu signalizující chybu
● Programátor musí neustále testovat, co funkce vrací
● Knihovna měla pro tyto účely vyhrazenu speciální proměnnou,
do níž se v případě chyby zapsal její kód; nahlédnutím do proměnné
program zjistil kód poslední chyby
● Programátor musí neustále testovat, jaká je v proměnné hodnota
► Některé jazyky (Cobol, PL/1, …) proto přišly s koncepcí
ošetření nestandardních situací
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
4
Ošetření nestandardních situací v Javě
► Výjimečná událost =
problém, který brání dalšímu vykonávání části kódu
► Událost je výjimečná v tom, že na rozdíl od běžných problémů
nemá program k vyřešení situace dost informaci
► Program může při výskytu výjimečné události vyvolat výjimku
► Výjimka (exception)
objekt určený k přenosu informací o nastalém problému
z místa jeho vzniku do místa, kde bude problém řešen
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
5
Postup při vyvolání výjimky
1. Vytvoří se výjimka = objekt typu Throwable
(prakticky vždy instance některého z potomků)
2. Vytvořená výjimka se vyhodí =
přeruší se běh programu v místě, kde výjimka vznikla,
a začne se hledat místo, kde bude daná výjimka ošetřena
3. Ošetření výjimky (handler) by mělo uvést program do stavu,
v němž může jeho vykonávání pokračovat
► Výjimka „probublává“ programem z místa vyhození stále výše
a nenarazí-li cestou nikde na své ošetření,
zachytí ji virtuální stroj, který na standardní chybový výstup
vypíše zprávu o vzniku výjimky
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
6
Systémová zpráva o vzniku výjimky
Zpráva o vzniku výjimky spolu s názvem vlákna,
v němž k výjimce došlo (zde AWT-EventQueue-0)
Popis druhu výjimky (aritmetická výjimka dělení nulou)
Informace o místě, odkud byla volána metoda,
která vyvolala metodu, v níž došlo k vyhození výjimky
Informace o místě, odkud byla volána metoda,
v níž došlo k vyhození výjimky
Úplný název třídy včetně balíčku
Copyright © 2006, Rudolf Pecinovský
Název metody
VŠE – 05
Název souboru se
zdrojovým kódem
Číslo řádku zdrojáku,
kde došlo k výjimce
7
Klíčová slova související s výjimkami
► try (zkus)
Označuje blok kódu, v němž může dojít k výjimce
► throw (hoď)
Příkaz k vyhození výjimky;
musí být následován odkazem na existující instanci
► catch (chyť)
Blok ošetřující výjimku, která je zadána jako parametr
► finally (na konec)
Blok s povinnými závěrečnými akcemi nezávisejícími
na případném vzniku výjimky
► throws (hází)
Uvození seznamu výjimek vyhazovaných danou metodou
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
8
Vyvolání a ošetření výjimky v kódu
try {
//Kód, který může vyvolat výjimky
}
catch( Typ1 id1 ) {
//Ošetření výjimek typu Typ1
}
...
catch( TypN idN ) {
//ošetření výjimek typu TypN
}
finally {
//Kód, který se na závěr VŽDY provede
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
9
Náznak činnosti – řádný průběh
nedojde k vyvolání výjimky
= nedojde k chybě
try {
příkaz1();
příkaz2();
příkaz3();
}
catch ( xxxException e ) {
příkazProOšetřeníChyby();
}
Bloky catch
catch (…..
se přeskočí
finally {
ukončovacíPříkazy();
}
dalšíPříkaz();
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
12
Náznak činnosti – ošetřený výjimka
try {
příkaz1(); Při provádění metody příkaz2
dojde k ošetřené chybě
příkaz2();
příkaz3();
Byla vyhozena výjimka
tohoto typu nebo typu
}
některého z potomků
catch ( xxxException e ) {
příkazProOšetřeníChyby();
}
Ostatní bloky catch
catch (…..
se přeskočí
finally {
ukončovacíPříkazy();
}
dalšíPříkaz();
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
13
Náznak činnosti – neošetřená výjimka
Při provádění metody příkaz2
dojde k NEošetřené chybě
try {
příkaz1();
příkaz2();
příkaz3();
}
catch ( xxxException e ) {
příkazProOšetřeníChyby();
}
Ošetření nebylo nalezeno =>
catch (…..
provede se blok finally
a opouští se metoda
finally {
ukončovacíPříkazy();
}
dalšíPříkaz();
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
14
Vyvolání výjimky
public class Xyz implements Comparable
{
public bolean compareTo( Object o )
{
if( !(o instanceOf Xyz) )
throw new ClassCastException (
"\nPokus o porovnání s neporovnatelnou"
+ " instancí " + o );
//Zjištění, kdo je větší
return vysledek;
}
}
► Instanci nemusíme vytvářet až v příkazu throw,
můžeme ji vytvořit kdykoliv před tím a pak mu ji jen předat
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
15
Vaše jistota na trhu IT
Výjimky kontrolované a
nekontrolované
►Hierarchie výjimek
►Pořadí výjimek v blocích catch
►Metody generující výjimky
►Metody třídy Throwable
►Zřetězené výjimky
►Převod kontrolovaných na nekontrolované
Charakteristika
► Výjimky, které jsou potomky třídy RuntimeException
nebo Error označujeme jako nekontrolované (unchecked),
protože překladač nekontroluje, zda je na ně program připraven
► Ostatní výjimky označujeme jako kontrolované (checked),
protože překladač kontroluje dodržení pravidel:
● Každá metoda, která může vyhodit kontrolovanou výjimku,
se musí k této skutečnosti veřejně přihlásit
● Každé použití metody, která může vyhodit kontrolovanou výjimku,
musí být buď uzavřeno v bloku try…catch,
nebo se volající metoda musí přihlásit k tomu,
že může také vyhodit danou kontrolovanou výjimku
► Nekontrolované výjimky ohlašují chyby v programu,
kontrolované výjimky očekávatelné situace,
na jejichž výskyt má být program připraven
a měl by na ně umět reagovat
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
17
Hierarchie výjimek
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
18
Pořadí výjimek v blocích catch
► Třída NumberFormatException
je potomkem třídy RuntimeException
try {
Syntaktická chyba,
......
na druhý blok catch nikdy nedojde
}
catch (RuntimeException e) {
.........
}
Obrácené pořadí bloků catch
catch (NumberFormatException e){
vše vyřeší
........
try {
}
......
}
catch (NumberFormatException e) {
.........
}
catch (RuntimeException e){
........
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
19
Metody generující výjimky
► Java vyžaduje, aby programy, které používají metody
schopné vyvolat kontrolované výjimky,
byly o této schopnosti používaných metod informovány =>
pak vědí, které výjimku musí umět zachytit a ošetřit
► Všechny kontrolované výjimky, které může metoda vyhodit,
musí deklarovat v hlavičce za klíčovým slovem throws
► Deklarace vyhazování nekontrolovaných výjimek není povinná
public void metoda()
throws KontrolovanáVýjimka1,
KontrolovanáVýjimka2
{
// Tělo metody
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
20
Metody třídy Throwable
► String getMessage()
Vrátí zprávu popisující danou výjimku
► String toString()
Vrátí název třídy výjimky následovaný případnou zprávou
► void printStackTrace()
Vytiskne toString() následovaný sadou informací o volající
posloupnosti, která vedla k vzniku výjimky
► Throwable fillInStackTrace()
Připraví nové informace o volací posloupnosti
vedoucí k místu zavolání této metody
► StackTraceElement[] getStackTrace()
Vrátí uchované informace o volací posloupnosti dané výjimky
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
21
Zřetězené výjimky
► V některých situacích je vhodné v rámci ošetření výjimky vyvolat
jinou výjimku, a přitom umožnit zjistit,
která výjimka byla prvotním hybatelem celé akce
► Řada výjimek má mezi svými konstruktory i takové,
které akceptují jako poslední parametr
odkaz na výjimku, jež byla příčinou vyvolání dané výjimky
► Chce-li se program zeptat výjimky na výjimku, která ji způsobila,
použije metodu
public Throwable getCause()
► Ve zprávě o vyvolání výjimky jsou místa, kde byla jedna výjimka
nahrazena jinou, označována textem caused by:
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
22
Ukázka výpisu při zřetězení výjimek
HighLevelException: MidLevelException: LowLevelException
at Junk.a(Junk.java:13)
at Junk.main(Junk.java:4)
Caused by: MidLevelException: LowLevelException
at Junk.c(Junk.java:23)
at Junk.b(Junk.java:17)
at Junk.a(Junk.java:11)
... 1 more
Caused by: LowLevelException
at Junk.e(Junk.java:30)
at Junk.d(Junk.java:27)
at Junk.c(Junk.java:21)
... 3 more
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
23
Převod kontrolovaných na nekontrolované
► Ošetřování kontrolovaných výjimek obtěžuje
► Víme-li, že k dané výjimce nejspíš nedojde
a ošetřujeme-li ji pouze proto, že na tom překladač trvá,
můžeme pro případ, že by k výjimce přece jenom došlo
zaměnit kontrolovanou výjimku za nekontrolovanou
public void prevod( String s ) {
try {
prověř( s );
} catch( Exception ex ) {
throw new RuntimeException( " Neprověřeno! ", ex );
}
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
24
Vaše jistota na trhu IT
Definice vlastních výjimek
►Hierarchie výjimek
►Pořadí výjimek v blocích catch
►Metody generující výjimky
►Metody třídy Throwable
►Vlastní výjimky
►Zásady správného používání výjimek
Definice vlastních výjimek
► Výjimky jsou zcela běžné třídy;
považujeme-li to proto za vhodné, můžeme definovat i vlastní
► Před definicí nové výjimky bychom si měli ujasnit,
bude-li kontrolovaná či nekontrolovaná;
podle toho definujeme jejího předka
► Název výjimek končí dle konvencí slovem Exception
před nímž je naznačena podstata dané výjimky
● IllegalArgumetnException
● NoSuchMethodException
● BadStringOperationException
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
26
Příklad vlastní kontrolované výjimky
public class VelkýPrůšvihException
extends Exception
{
public VelkýPrůšvihException() {};
public VelkýPrůšvihException( String zpráva ) {
super( zpráva );
}
public VelkýPrůšvihException(String zpráva,
Throwable původce ) {
super( zpráva, původce );
}
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
27
Test správného vyhození výjimky
► Na vytvářených programech je třeba otestovat i to,
že v definovaných situacích vyhodí požadovanou výjimku
public void testVyhozeníVýjimky()
{
try {
metodaKteráMáVyhoditVýjimku();
} catch ( VelkýPrůšvihException vpe ) {
return;
}
fail( "Nebyla vyhozena výjimka VelkýPrůšvihException" );
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
28
Zásady správného používání výjimek
1/2
Neignorujte
výjimky
try {
//Nějaký kód
}
catch(Exception e){}
► Výjimky, o nichž víte, že nemohou nastat,
převeďte na nekontrolované pro případ,
že by v budoucích verzích programu nastat mohly
► Při ošetřování výjimek, které nastat mohou,
ale nemají vliv na chod programu,
vložte do těla ošetření alespoň vysvětlující komentář
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
29
Zásady správného používání výjimek
2/2
► Používejte výjimky pouze k ošetření výjimečných stavů
► Kontrolované výjimky používejte u stavů, z nichž se lze zotavit,
jinak použijte výjimky nekontrolované
► Vyhýbejte se zbytečnému používání kontrolovaných výjimek
● Programátory ošetřování kontrolovaných výjimek obtěžuje
a mají pak tendenci je ošetřovat prázdným blokem catch
► Dávejte přednost standardním výjimkám,
vyvolávejte výjimky odpovídající dané abstrakci
● Programátoři by měli z názvu výjimky poznat, co se stalo
● Standardní výjimky mají všeobecně známý význam
► Snažte se o atomičnost selhání; i po vyhození výjimky
by měl být objekt v dobře definovaném stavu
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
30
Zásady správného používání výjimek
3/2
► Doplňujte výjimky zprávami,
výjimka by sama měla poskytnout dostatek informací
a neměla by programátora nutit k podrobnější analýze programu
► Dokumentujte vyvolávané výjimky v dokumentačních
komentářích pomocí značky @throws
► Nedělejte bloky try zbytečně velké,
kód uvnitř těchto bloků se neoptimalizuje
► Umíte-li výjimku v metodě ošetřit, udělejte to
► Detekuje-li se chyba v jedné metodě a má se ošetřit v jiné
(stejné či jiné instance), použijte výjimku.
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
31
Nejčastěji používané výjimky
1/2
► IllegalArgumentException
Byla zadána nepovolená hodnota parametru
● Např. chci nastavit zápornou velikost grafického tvaru
► IllegalStateException
V daném stavu objektu nelze metodu provést
● Např. otevřu soubor, přečtu pár vět, zavřu soubor a chci znovu přečíst větu
► NullPointerException
Byla vyvolána metoda instance, na níž ukazuje prázdný odkaz,
nebo byl předán nepovolený prázdný odkaz v parametru
► ArrayIndexOutOfBoundException
Byly zadány špatné meze pole, buď záporné nebo moc velké
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
32
Nejčastěji používané výjimky
2/2
► ConcurrentModificationException
V průběhu iterace byla změněna struktura kontejneru
● Např. byl do kontejneru přidán prvek
► NumberFormatException
Je požadován špatný převod řetězce na číslo či naopak
● Chci-li např. převést na číslo řetězec, který není číslem
● Častá chyba v metodách String.format či PrintStream.printf
► ClassCastException
Požadované přetypování není možné
► UnsupportedOperationException
Požadovaná operace není podporována
(např. chci přidat prvek do neměnného kontejneru)
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
33
Vaše jistota na trhu IT
Děkuji za pozornost
►Rudolf Pecinovský
http://vyuka.pecinovsky.cz/vse
mail: [email protected]
ICQ: 158 156 600
Slide 19
Vaše jistota na trhu IT
Výjimky
Rudolf Pecinovský
[email protected]
Vaše jistota na trhu IT
Obsah s odkazy
►Výjimky
►Výjimky kontrolované a nekontrolované
►Definice vlastních výjimek
Vaše jistota na trhu IT
Výjimky
►Výjimečné situace v programech
►Ošetření nestandardních situací v Javě
►Zpráva o výjimce
►Klíčová slova
►Činnost
►Vyvolání
Výjimečné situace v programech
► V každém programu je alespoň jedna chyba –
program na ni musí být připraven
► Starší programy
● Program vypsal chybové hlášení a ukončil činnost;
● V některých situacích (válcovací stolice, autopilot, …) nepřijatelné
● Funkce vrátí hodnotu signalizující chybu
● Programátor musí neustále testovat, co funkce vrací
● Knihovna měla pro tyto účely vyhrazenu speciální proměnnou,
do níž se v případě chyby zapsal její kód; nahlédnutím do proměnné
program zjistil kód poslední chyby
● Programátor musí neustále testovat, jaká je v proměnné hodnota
► Některé jazyky (Cobol, PL/1, …) proto přišly s koncepcí
ošetření nestandardních situací
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
4
Ošetření nestandardních situací v Javě
► Výjimečná událost =
problém, který brání dalšímu vykonávání části kódu
► Událost je výjimečná v tom, že na rozdíl od běžných problémů
nemá program k vyřešení situace dost informaci
► Program může při výskytu výjimečné události vyvolat výjimku
► Výjimka (exception)
objekt určený k přenosu informací o nastalém problému
z místa jeho vzniku do místa, kde bude problém řešen
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
5
Postup při vyvolání výjimky
1. Vytvoří se výjimka = objekt typu Throwable
(prakticky vždy instance některého z potomků)
2. Vytvořená výjimka se vyhodí =
přeruší se běh programu v místě, kde výjimka vznikla,
a začne se hledat místo, kde bude daná výjimka ošetřena
3. Ošetření výjimky (handler) by mělo uvést program do stavu,
v němž může jeho vykonávání pokračovat
► Výjimka „probublává“ programem z místa vyhození stále výše
a nenarazí-li cestou nikde na své ošetření,
zachytí ji virtuální stroj, který na standardní chybový výstup
vypíše zprávu o vzniku výjimky
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
6
Systémová zpráva o vzniku výjimky
Zpráva o vzniku výjimky spolu s názvem vlákna,
v němž k výjimce došlo (zde AWT-EventQueue-0)
Popis druhu výjimky (aritmetická výjimka dělení nulou)
Informace o místě, odkud byla volána metoda,
která vyvolala metodu, v níž došlo k vyhození výjimky
Informace o místě, odkud byla volána metoda,
v níž došlo k vyhození výjimky
Úplný název třídy včetně balíčku
Copyright © 2006, Rudolf Pecinovský
Název metody
VŠE – 05
Název souboru se
zdrojovým kódem
Číslo řádku zdrojáku,
kde došlo k výjimce
7
Klíčová slova související s výjimkami
► try (zkus)
Označuje blok kódu, v němž může dojít k výjimce
► throw (hoď)
Příkaz k vyhození výjimky;
musí být následován odkazem na existující instanci
► catch (chyť)
Blok ošetřující výjimku, která je zadána jako parametr
► finally (na konec)
Blok s povinnými závěrečnými akcemi nezávisejícími
na případném vzniku výjimky
► throws (hází)
Uvození seznamu výjimek vyhazovaných danou metodou
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
8
Vyvolání a ošetření výjimky v kódu
try {
//Kód, který může vyvolat výjimky
}
catch( Typ1 id1 ) {
//Ošetření výjimek typu Typ1
}
...
catch( TypN idN ) {
//ošetření výjimek typu TypN
}
finally {
//Kód, který se na závěr VŽDY provede
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
9
Náznak činnosti – řádný průběh
nedojde k vyvolání výjimky
= nedojde k chybě
try {
příkaz1();
příkaz2();
příkaz3();
}
catch ( xxxException e ) {
příkazProOšetřeníChyby();
}
Bloky catch
catch (…..
se přeskočí
finally {
ukončovacíPříkazy();
}
dalšíPříkaz();
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
12
Náznak činnosti – ošetřený výjimka
try {
příkaz1(); Při provádění metody příkaz2
dojde k ošetřené chybě
příkaz2();
příkaz3();
Byla vyhozena výjimka
tohoto typu nebo typu
}
některého z potomků
catch ( xxxException e ) {
příkazProOšetřeníChyby();
}
Ostatní bloky catch
catch (…..
se přeskočí
finally {
ukončovacíPříkazy();
}
dalšíPříkaz();
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
13
Náznak činnosti – neošetřená výjimka
Při provádění metody příkaz2
dojde k NEošetřené chybě
try {
příkaz1();
příkaz2();
příkaz3();
}
catch ( xxxException e ) {
příkazProOšetřeníChyby();
}
Ošetření nebylo nalezeno =>
catch (…..
provede se blok finally
a opouští se metoda
finally {
ukončovacíPříkazy();
}
dalšíPříkaz();
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
14
Vyvolání výjimky
public class Xyz implements Comparable
{
public bolean compareTo( Object o )
{
if( !(o instanceOf Xyz) )
throw new ClassCastException (
"\nPokus o porovnání s neporovnatelnou"
+ " instancí " + o );
//Zjištění, kdo je větší
return vysledek;
}
}
► Instanci nemusíme vytvářet až v příkazu throw,
můžeme ji vytvořit kdykoliv před tím a pak mu ji jen předat
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
15
Vaše jistota na trhu IT
Výjimky kontrolované a
nekontrolované
►Hierarchie výjimek
►Pořadí výjimek v blocích catch
►Metody generující výjimky
►Metody třídy Throwable
►Zřetězené výjimky
►Převod kontrolovaných na nekontrolované
Charakteristika
► Výjimky, které jsou potomky třídy RuntimeException
nebo Error označujeme jako nekontrolované (unchecked),
protože překladač nekontroluje, zda je na ně program připraven
► Ostatní výjimky označujeme jako kontrolované (checked),
protože překladač kontroluje dodržení pravidel:
● Každá metoda, která může vyhodit kontrolovanou výjimku,
se musí k této skutečnosti veřejně přihlásit
● Každé použití metody, která může vyhodit kontrolovanou výjimku,
musí být buď uzavřeno v bloku try…catch,
nebo se volající metoda musí přihlásit k tomu,
že může také vyhodit danou kontrolovanou výjimku
► Nekontrolované výjimky ohlašují chyby v programu,
kontrolované výjimky očekávatelné situace,
na jejichž výskyt má být program připraven
a měl by na ně umět reagovat
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
17
Hierarchie výjimek
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
18
Pořadí výjimek v blocích catch
► Třída NumberFormatException
je potomkem třídy RuntimeException
try {
Syntaktická chyba,
......
na druhý blok catch nikdy nedojde
}
catch (RuntimeException e) {
.........
}
Obrácené pořadí bloků catch
catch (NumberFormatException e){
vše vyřeší
........
try {
}
......
}
catch (NumberFormatException e) {
.........
}
catch (RuntimeException e){
........
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
19
Metody generující výjimky
► Java vyžaduje, aby programy, které používají metody
schopné vyvolat kontrolované výjimky,
byly o této schopnosti používaných metod informovány =>
pak vědí, které výjimku musí umět zachytit a ošetřit
► Všechny kontrolované výjimky, které může metoda vyhodit,
musí deklarovat v hlavičce za klíčovým slovem throws
► Deklarace vyhazování nekontrolovaných výjimek není povinná
public void metoda()
throws KontrolovanáVýjimka1,
KontrolovanáVýjimka2
{
// Tělo metody
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
20
Metody třídy Throwable
► String getMessage()
Vrátí zprávu popisující danou výjimku
► String toString()
Vrátí název třídy výjimky následovaný případnou zprávou
► void printStackTrace()
Vytiskne toString() následovaný sadou informací o volající
posloupnosti, která vedla k vzniku výjimky
► Throwable fillInStackTrace()
Připraví nové informace o volací posloupnosti
vedoucí k místu zavolání této metody
► StackTraceElement[] getStackTrace()
Vrátí uchované informace o volací posloupnosti dané výjimky
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
21
Zřetězené výjimky
► V některých situacích je vhodné v rámci ošetření výjimky vyvolat
jinou výjimku, a přitom umožnit zjistit,
která výjimka byla prvotním hybatelem celé akce
► Řada výjimek má mezi svými konstruktory i takové,
které akceptují jako poslední parametr
odkaz na výjimku, jež byla příčinou vyvolání dané výjimky
► Chce-li se program zeptat výjimky na výjimku, která ji způsobila,
použije metodu
public Throwable getCause()
► Ve zprávě o vyvolání výjimky jsou místa, kde byla jedna výjimka
nahrazena jinou, označována textem caused by:
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
22
Ukázka výpisu při zřetězení výjimek
HighLevelException: MidLevelException: LowLevelException
at Junk.a(Junk.java:13)
at Junk.main(Junk.java:4)
Caused by: MidLevelException: LowLevelException
at Junk.c(Junk.java:23)
at Junk.b(Junk.java:17)
at Junk.a(Junk.java:11)
... 1 more
Caused by: LowLevelException
at Junk.e(Junk.java:30)
at Junk.d(Junk.java:27)
at Junk.c(Junk.java:21)
... 3 more
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
23
Převod kontrolovaných na nekontrolované
► Ošetřování kontrolovaných výjimek obtěžuje
► Víme-li, že k dané výjimce nejspíš nedojde
a ošetřujeme-li ji pouze proto, že na tom překladač trvá,
můžeme pro případ, že by k výjimce přece jenom došlo
zaměnit kontrolovanou výjimku za nekontrolovanou
public void prevod( String s ) {
try {
prověř( s );
} catch( Exception ex ) {
throw new RuntimeException( " Neprověřeno! ", ex );
}
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
24
Vaše jistota na trhu IT
Definice vlastních výjimek
►Hierarchie výjimek
►Pořadí výjimek v blocích catch
►Metody generující výjimky
►Metody třídy Throwable
►Vlastní výjimky
►Zásady správného používání výjimek
Definice vlastních výjimek
► Výjimky jsou zcela běžné třídy;
považujeme-li to proto za vhodné, můžeme definovat i vlastní
► Před definicí nové výjimky bychom si měli ujasnit,
bude-li kontrolovaná či nekontrolovaná;
podle toho definujeme jejího předka
► Název výjimek končí dle konvencí slovem Exception
před nímž je naznačena podstata dané výjimky
● IllegalArgumetnException
● NoSuchMethodException
● BadStringOperationException
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
26
Příklad vlastní kontrolované výjimky
public class VelkýPrůšvihException
extends Exception
{
public VelkýPrůšvihException() {};
public VelkýPrůšvihException( String zpráva ) {
super( zpráva );
}
public VelkýPrůšvihException(String zpráva,
Throwable původce ) {
super( zpráva, původce );
}
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
27
Test správného vyhození výjimky
► Na vytvářených programech je třeba otestovat i to,
že v definovaných situacích vyhodí požadovanou výjimku
public void testVyhozeníVýjimky()
{
try {
metodaKteráMáVyhoditVýjimku();
} catch ( VelkýPrůšvihException vpe ) {
return;
}
fail( "Nebyla vyhozena výjimka VelkýPrůšvihException" );
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
28
Zásady správného používání výjimek
1/2
Neignorujte
výjimky
try {
//Nějaký kód
}
catch(Exception e){}
► Výjimky, o nichž víte, že nemohou nastat,
převeďte na nekontrolované pro případ,
že by v budoucích verzích programu nastat mohly
► Při ošetřování výjimek, které nastat mohou,
ale nemají vliv na chod programu,
vložte do těla ošetření alespoň vysvětlující komentář
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
29
Zásady správného používání výjimek
2/2
► Používejte výjimky pouze k ošetření výjimečných stavů
► Kontrolované výjimky používejte u stavů, z nichž se lze zotavit,
jinak použijte výjimky nekontrolované
► Vyhýbejte se zbytečnému používání kontrolovaných výjimek
● Programátory ošetřování kontrolovaných výjimek obtěžuje
a mají pak tendenci je ošetřovat prázdným blokem catch
► Dávejte přednost standardním výjimkám,
vyvolávejte výjimky odpovídající dané abstrakci
● Programátoři by měli z názvu výjimky poznat, co se stalo
● Standardní výjimky mají všeobecně známý význam
► Snažte se o atomičnost selhání; i po vyhození výjimky
by měl být objekt v dobře definovaném stavu
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
30
Zásady správného používání výjimek
3/2
► Doplňujte výjimky zprávami,
výjimka by sama měla poskytnout dostatek informací
a neměla by programátora nutit k podrobnější analýze programu
► Dokumentujte vyvolávané výjimky v dokumentačních
komentářích pomocí značky @throws
► Nedělejte bloky try zbytečně velké,
kód uvnitř těchto bloků se neoptimalizuje
► Umíte-li výjimku v metodě ošetřit, udělejte to
► Detekuje-li se chyba v jedné metodě a má se ošetřit v jiné
(stejné či jiné instance), použijte výjimku.
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
31
Nejčastěji používané výjimky
1/2
► IllegalArgumentException
Byla zadána nepovolená hodnota parametru
● Např. chci nastavit zápornou velikost grafického tvaru
► IllegalStateException
V daném stavu objektu nelze metodu provést
● Např. otevřu soubor, přečtu pár vět, zavřu soubor a chci znovu přečíst větu
► NullPointerException
Byla vyvolána metoda instance, na níž ukazuje prázdný odkaz,
nebo byl předán nepovolený prázdný odkaz v parametru
► ArrayIndexOutOfBoundException
Byly zadány špatné meze pole, buď záporné nebo moc velké
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
32
Nejčastěji používané výjimky
2/2
► ConcurrentModificationException
V průběhu iterace byla změněna struktura kontejneru
● Např. byl do kontejneru přidán prvek
► NumberFormatException
Je požadován špatný převod řetězce na číslo či naopak
● Chci-li např. převést na číslo řetězec, který není číslem
● Častá chyba v metodách String.format či PrintStream.printf
► ClassCastException
Požadované přetypování není možné
► UnsupportedOperationException
Požadovaná operace není podporována
(např. chci přidat prvek do neměnného kontejneru)
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
33
Vaše jistota na trhu IT
Děkuji za pozornost
►Rudolf Pecinovský
http://vyuka.pecinovsky.cz/vse
mail: [email protected]
ICQ: 158 156 600
Slide 20
Vaše jistota na trhu IT
Výjimky
Rudolf Pecinovský
[email protected]
Vaše jistota na trhu IT
Obsah s odkazy
►Výjimky
►Výjimky kontrolované a nekontrolované
►Definice vlastních výjimek
Vaše jistota na trhu IT
Výjimky
►Výjimečné situace v programech
►Ošetření nestandardních situací v Javě
►Zpráva o výjimce
►Klíčová slova
►Činnost
►Vyvolání
Výjimečné situace v programech
► V každém programu je alespoň jedna chyba –
program na ni musí být připraven
► Starší programy
● Program vypsal chybové hlášení a ukončil činnost;
● V některých situacích (válcovací stolice, autopilot, …) nepřijatelné
● Funkce vrátí hodnotu signalizující chybu
● Programátor musí neustále testovat, co funkce vrací
● Knihovna měla pro tyto účely vyhrazenu speciální proměnnou,
do níž se v případě chyby zapsal její kód; nahlédnutím do proměnné
program zjistil kód poslední chyby
● Programátor musí neustále testovat, jaká je v proměnné hodnota
► Některé jazyky (Cobol, PL/1, …) proto přišly s koncepcí
ošetření nestandardních situací
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
4
Ošetření nestandardních situací v Javě
► Výjimečná událost =
problém, který brání dalšímu vykonávání části kódu
► Událost je výjimečná v tom, že na rozdíl od běžných problémů
nemá program k vyřešení situace dost informaci
► Program může při výskytu výjimečné události vyvolat výjimku
► Výjimka (exception)
objekt určený k přenosu informací o nastalém problému
z místa jeho vzniku do místa, kde bude problém řešen
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
5
Postup při vyvolání výjimky
1. Vytvoří se výjimka = objekt typu Throwable
(prakticky vždy instance některého z potomků)
2. Vytvořená výjimka se vyhodí =
přeruší se běh programu v místě, kde výjimka vznikla,
a začne se hledat místo, kde bude daná výjimka ošetřena
3. Ošetření výjimky (handler) by mělo uvést program do stavu,
v němž může jeho vykonávání pokračovat
► Výjimka „probublává“ programem z místa vyhození stále výše
a nenarazí-li cestou nikde na své ošetření,
zachytí ji virtuální stroj, který na standardní chybový výstup
vypíše zprávu o vzniku výjimky
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
6
Systémová zpráva o vzniku výjimky
Zpráva o vzniku výjimky spolu s názvem vlákna,
v němž k výjimce došlo (zde AWT-EventQueue-0)
Popis druhu výjimky (aritmetická výjimka dělení nulou)
Informace o místě, odkud byla volána metoda,
která vyvolala metodu, v níž došlo k vyhození výjimky
Informace o místě, odkud byla volána metoda,
v níž došlo k vyhození výjimky
Úplný název třídy včetně balíčku
Copyright © 2006, Rudolf Pecinovský
Název metody
VŠE – 05
Název souboru se
zdrojovým kódem
Číslo řádku zdrojáku,
kde došlo k výjimce
7
Klíčová slova související s výjimkami
► try (zkus)
Označuje blok kódu, v němž může dojít k výjimce
► throw (hoď)
Příkaz k vyhození výjimky;
musí být následován odkazem na existující instanci
► catch (chyť)
Blok ošetřující výjimku, která je zadána jako parametr
► finally (na konec)
Blok s povinnými závěrečnými akcemi nezávisejícími
na případném vzniku výjimky
► throws (hází)
Uvození seznamu výjimek vyhazovaných danou metodou
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
8
Vyvolání a ošetření výjimky v kódu
try {
//Kód, který může vyvolat výjimky
}
catch( Typ1 id1 ) {
//Ošetření výjimek typu Typ1
}
...
catch( TypN idN ) {
//ošetření výjimek typu TypN
}
finally {
//Kód, který se na závěr VŽDY provede
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
9
Náznak činnosti – řádný průběh
nedojde k vyvolání výjimky
= nedojde k chybě
try {
příkaz1();
příkaz2();
příkaz3();
}
catch ( xxxException e ) {
příkazProOšetřeníChyby();
}
Bloky catch
catch (…..
se přeskočí
finally {
ukončovacíPříkazy();
}
dalšíPříkaz();
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
12
Náznak činnosti – ošetřený výjimka
try {
příkaz1(); Při provádění metody příkaz2
dojde k ošetřené chybě
příkaz2();
příkaz3();
Byla vyhozena výjimka
tohoto typu nebo typu
}
některého z potomků
catch ( xxxException e ) {
příkazProOšetřeníChyby();
}
Ostatní bloky catch
catch (…..
se přeskočí
finally {
ukončovacíPříkazy();
}
dalšíPříkaz();
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
13
Náznak činnosti – neošetřená výjimka
Při provádění metody příkaz2
dojde k NEošetřené chybě
try {
příkaz1();
příkaz2();
příkaz3();
}
catch ( xxxException e ) {
příkazProOšetřeníChyby();
}
Ošetření nebylo nalezeno =>
catch (…..
provede se blok finally
a opouští se metoda
finally {
ukončovacíPříkazy();
}
dalšíPříkaz();
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
14
Vyvolání výjimky
public class Xyz implements Comparable
{
public bolean compareTo( Object o )
{
if( !(o instanceOf Xyz) )
throw new ClassCastException (
"\nPokus o porovnání s neporovnatelnou"
+ " instancí " + o );
//Zjištění, kdo je větší
return vysledek;
}
}
► Instanci nemusíme vytvářet až v příkazu throw,
můžeme ji vytvořit kdykoliv před tím a pak mu ji jen předat
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
15
Vaše jistota na trhu IT
Výjimky kontrolované a
nekontrolované
►Hierarchie výjimek
►Pořadí výjimek v blocích catch
►Metody generující výjimky
►Metody třídy Throwable
►Zřetězené výjimky
►Převod kontrolovaných na nekontrolované
Charakteristika
► Výjimky, které jsou potomky třídy RuntimeException
nebo Error označujeme jako nekontrolované (unchecked),
protože překladač nekontroluje, zda je na ně program připraven
► Ostatní výjimky označujeme jako kontrolované (checked),
protože překladač kontroluje dodržení pravidel:
● Každá metoda, která může vyhodit kontrolovanou výjimku,
se musí k této skutečnosti veřejně přihlásit
● Každé použití metody, která může vyhodit kontrolovanou výjimku,
musí být buď uzavřeno v bloku try…catch,
nebo se volající metoda musí přihlásit k tomu,
že může také vyhodit danou kontrolovanou výjimku
► Nekontrolované výjimky ohlašují chyby v programu,
kontrolované výjimky očekávatelné situace,
na jejichž výskyt má být program připraven
a měl by na ně umět reagovat
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
17
Hierarchie výjimek
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
18
Pořadí výjimek v blocích catch
► Třída NumberFormatException
je potomkem třídy RuntimeException
try {
Syntaktická chyba,
......
na druhý blok catch nikdy nedojde
}
catch (RuntimeException e) {
.........
}
Obrácené pořadí bloků catch
catch (NumberFormatException e){
vše vyřeší
........
try {
}
......
}
catch (NumberFormatException e) {
.........
}
catch (RuntimeException e){
........
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
19
Metody generující výjimky
► Java vyžaduje, aby programy, které používají metody
schopné vyvolat kontrolované výjimky,
byly o této schopnosti používaných metod informovány =>
pak vědí, které výjimku musí umět zachytit a ošetřit
► Všechny kontrolované výjimky, které může metoda vyhodit,
musí deklarovat v hlavičce za klíčovým slovem throws
► Deklarace vyhazování nekontrolovaných výjimek není povinná
public void metoda()
throws KontrolovanáVýjimka1,
KontrolovanáVýjimka2
{
// Tělo metody
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
20
Metody třídy Throwable
► String getMessage()
Vrátí zprávu popisující danou výjimku
► String toString()
Vrátí název třídy výjimky následovaný případnou zprávou
► void printStackTrace()
Vytiskne toString() následovaný sadou informací o volající
posloupnosti, která vedla k vzniku výjimky
► Throwable fillInStackTrace()
Připraví nové informace o volací posloupnosti
vedoucí k místu zavolání této metody
► StackTraceElement[] getStackTrace()
Vrátí uchované informace o volací posloupnosti dané výjimky
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
21
Zřetězené výjimky
► V některých situacích je vhodné v rámci ošetření výjimky vyvolat
jinou výjimku, a přitom umožnit zjistit,
která výjimka byla prvotním hybatelem celé akce
► Řada výjimek má mezi svými konstruktory i takové,
které akceptují jako poslední parametr
odkaz na výjimku, jež byla příčinou vyvolání dané výjimky
► Chce-li se program zeptat výjimky na výjimku, která ji způsobila,
použije metodu
public Throwable getCause()
► Ve zprávě o vyvolání výjimky jsou místa, kde byla jedna výjimka
nahrazena jinou, označována textem caused by:
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
22
Ukázka výpisu při zřetězení výjimek
HighLevelException: MidLevelException: LowLevelException
at Junk.a(Junk.java:13)
at Junk.main(Junk.java:4)
Caused by: MidLevelException: LowLevelException
at Junk.c(Junk.java:23)
at Junk.b(Junk.java:17)
at Junk.a(Junk.java:11)
... 1 more
Caused by: LowLevelException
at Junk.e(Junk.java:30)
at Junk.d(Junk.java:27)
at Junk.c(Junk.java:21)
... 3 more
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
23
Převod kontrolovaných na nekontrolované
► Ošetřování kontrolovaných výjimek obtěžuje
► Víme-li, že k dané výjimce nejspíš nedojde
a ošetřujeme-li ji pouze proto, že na tom překladač trvá,
můžeme pro případ, že by k výjimce přece jenom došlo
zaměnit kontrolovanou výjimku za nekontrolovanou
public void prevod( String s ) {
try {
prověř( s );
} catch( Exception ex ) {
throw new RuntimeException( " Neprověřeno! ", ex );
}
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
24
Vaše jistota na trhu IT
Definice vlastních výjimek
►Hierarchie výjimek
►Pořadí výjimek v blocích catch
►Metody generující výjimky
►Metody třídy Throwable
►Vlastní výjimky
►Zásady správného používání výjimek
Definice vlastních výjimek
► Výjimky jsou zcela běžné třídy;
považujeme-li to proto za vhodné, můžeme definovat i vlastní
► Před definicí nové výjimky bychom si měli ujasnit,
bude-li kontrolovaná či nekontrolovaná;
podle toho definujeme jejího předka
► Název výjimek končí dle konvencí slovem Exception
před nímž je naznačena podstata dané výjimky
● IllegalArgumetnException
● NoSuchMethodException
● BadStringOperationException
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
26
Příklad vlastní kontrolované výjimky
public class VelkýPrůšvihException
extends Exception
{
public VelkýPrůšvihException() {};
public VelkýPrůšvihException( String zpráva ) {
super( zpráva );
}
public VelkýPrůšvihException(String zpráva,
Throwable původce ) {
super( zpráva, původce );
}
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
27
Test správného vyhození výjimky
► Na vytvářených programech je třeba otestovat i to,
že v definovaných situacích vyhodí požadovanou výjimku
public void testVyhozeníVýjimky()
{
try {
metodaKteráMáVyhoditVýjimku();
} catch ( VelkýPrůšvihException vpe ) {
return;
}
fail( "Nebyla vyhozena výjimka VelkýPrůšvihException" );
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
28
Zásady správného používání výjimek
1/2
Neignorujte
výjimky
try {
//Nějaký kód
}
catch(Exception e){}
► Výjimky, o nichž víte, že nemohou nastat,
převeďte na nekontrolované pro případ,
že by v budoucích verzích programu nastat mohly
► Při ošetřování výjimek, které nastat mohou,
ale nemají vliv na chod programu,
vložte do těla ošetření alespoň vysvětlující komentář
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
29
Zásady správného používání výjimek
2/2
► Používejte výjimky pouze k ošetření výjimečných stavů
► Kontrolované výjimky používejte u stavů, z nichž se lze zotavit,
jinak použijte výjimky nekontrolované
► Vyhýbejte se zbytečnému používání kontrolovaných výjimek
● Programátory ošetřování kontrolovaných výjimek obtěžuje
a mají pak tendenci je ošetřovat prázdným blokem catch
► Dávejte přednost standardním výjimkám,
vyvolávejte výjimky odpovídající dané abstrakci
● Programátoři by měli z názvu výjimky poznat, co se stalo
● Standardní výjimky mají všeobecně známý význam
► Snažte se o atomičnost selhání; i po vyhození výjimky
by měl být objekt v dobře definovaném stavu
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
30
Zásady správného používání výjimek
3/2
► Doplňujte výjimky zprávami,
výjimka by sama měla poskytnout dostatek informací
a neměla by programátora nutit k podrobnější analýze programu
► Dokumentujte vyvolávané výjimky v dokumentačních
komentářích pomocí značky @throws
► Nedělejte bloky try zbytečně velké,
kód uvnitř těchto bloků se neoptimalizuje
► Umíte-li výjimku v metodě ošetřit, udělejte to
► Detekuje-li se chyba v jedné metodě a má se ošetřit v jiné
(stejné či jiné instance), použijte výjimku.
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
31
Nejčastěji používané výjimky
1/2
► IllegalArgumentException
Byla zadána nepovolená hodnota parametru
● Např. chci nastavit zápornou velikost grafického tvaru
► IllegalStateException
V daném stavu objektu nelze metodu provést
● Např. otevřu soubor, přečtu pár vět, zavřu soubor a chci znovu přečíst větu
► NullPointerException
Byla vyvolána metoda instance, na níž ukazuje prázdný odkaz,
nebo byl předán nepovolený prázdný odkaz v parametru
► ArrayIndexOutOfBoundException
Byly zadány špatné meze pole, buď záporné nebo moc velké
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
32
Nejčastěji používané výjimky
2/2
► ConcurrentModificationException
V průběhu iterace byla změněna struktura kontejneru
● Např. byl do kontejneru přidán prvek
► NumberFormatException
Je požadován špatný převod řetězce na číslo či naopak
● Chci-li např. převést na číslo řetězec, který není číslem
● Častá chyba v metodách String.format či PrintStream.printf
► ClassCastException
Požadované přetypování není možné
► UnsupportedOperationException
Požadovaná operace není podporována
(např. chci přidat prvek do neměnného kontejneru)
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
33
Vaše jistota na trhu IT
Děkuji za pozornost
►Rudolf Pecinovský
http://vyuka.pecinovsky.cz/vse
mail: [email protected]
ICQ: 158 156 600
Slide 21
Vaše jistota na trhu IT
Výjimky
Rudolf Pecinovský
[email protected]
Vaše jistota na trhu IT
Obsah s odkazy
►Výjimky
►Výjimky kontrolované a nekontrolované
►Definice vlastních výjimek
Vaše jistota na trhu IT
Výjimky
►Výjimečné situace v programech
►Ošetření nestandardních situací v Javě
►Zpráva o výjimce
►Klíčová slova
►Činnost
►Vyvolání
Výjimečné situace v programech
► V každém programu je alespoň jedna chyba –
program na ni musí být připraven
► Starší programy
● Program vypsal chybové hlášení a ukončil činnost;
● V některých situacích (válcovací stolice, autopilot, …) nepřijatelné
● Funkce vrátí hodnotu signalizující chybu
● Programátor musí neustále testovat, co funkce vrací
● Knihovna měla pro tyto účely vyhrazenu speciální proměnnou,
do níž se v případě chyby zapsal její kód; nahlédnutím do proměnné
program zjistil kód poslední chyby
● Programátor musí neustále testovat, jaká je v proměnné hodnota
► Některé jazyky (Cobol, PL/1, …) proto přišly s koncepcí
ošetření nestandardních situací
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
4
Ošetření nestandardních situací v Javě
► Výjimečná událost =
problém, který brání dalšímu vykonávání části kódu
► Událost je výjimečná v tom, že na rozdíl od běžných problémů
nemá program k vyřešení situace dost informaci
► Program může při výskytu výjimečné události vyvolat výjimku
► Výjimka (exception)
objekt určený k přenosu informací o nastalém problému
z místa jeho vzniku do místa, kde bude problém řešen
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
5
Postup při vyvolání výjimky
1. Vytvoří se výjimka = objekt typu Throwable
(prakticky vždy instance některého z potomků)
2. Vytvořená výjimka se vyhodí =
přeruší se běh programu v místě, kde výjimka vznikla,
a začne se hledat místo, kde bude daná výjimka ošetřena
3. Ošetření výjimky (handler) by mělo uvést program do stavu,
v němž může jeho vykonávání pokračovat
► Výjimka „probublává“ programem z místa vyhození stále výše
a nenarazí-li cestou nikde na své ošetření,
zachytí ji virtuální stroj, který na standardní chybový výstup
vypíše zprávu o vzniku výjimky
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
6
Systémová zpráva o vzniku výjimky
Zpráva o vzniku výjimky spolu s názvem vlákna,
v němž k výjimce došlo (zde AWT-EventQueue-0)
Popis druhu výjimky (aritmetická výjimka dělení nulou)
Informace o místě, odkud byla volána metoda,
která vyvolala metodu, v níž došlo k vyhození výjimky
Informace o místě, odkud byla volána metoda,
v níž došlo k vyhození výjimky
Úplný název třídy včetně balíčku
Copyright © 2006, Rudolf Pecinovský
Název metody
VŠE – 05
Název souboru se
zdrojovým kódem
Číslo řádku zdrojáku,
kde došlo k výjimce
7
Klíčová slova související s výjimkami
► try (zkus)
Označuje blok kódu, v němž může dojít k výjimce
► throw (hoď)
Příkaz k vyhození výjimky;
musí být následován odkazem na existující instanci
► catch (chyť)
Blok ošetřující výjimku, která je zadána jako parametr
► finally (na konec)
Blok s povinnými závěrečnými akcemi nezávisejícími
na případném vzniku výjimky
► throws (hází)
Uvození seznamu výjimek vyhazovaných danou metodou
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
8
Vyvolání a ošetření výjimky v kódu
try {
//Kód, který může vyvolat výjimky
}
catch( Typ1 id1 ) {
//Ošetření výjimek typu Typ1
}
...
catch( TypN idN ) {
//ošetření výjimek typu TypN
}
finally {
//Kód, který se na závěr VŽDY provede
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
9
Náznak činnosti – řádný průběh
nedojde k vyvolání výjimky
= nedojde k chybě
try {
příkaz1();
příkaz2();
příkaz3();
}
catch ( xxxException e ) {
příkazProOšetřeníChyby();
}
Bloky catch
catch (…..
se přeskočí
finally {
ukončovacíPříkazy();
}
dalšíPříkaz();
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
12
Náznak činnosti – ošetřený výjimka
try {
příkaz1(); Při provádění metody příkaz2
dojde k ošetřené chybě
příkaz2();
příkaz3();
Byla vyhozena výjimka
tohoto typu nebo typu
}
některého z potomků
catch ( xxxException e ) {
příkazProOšetřeníChyby();
}
Ostatní bloky catch
catch (…..
se přeskočí
finally {
ukončovacíPříkazy();
}
dalšíPříkaz();
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
13
Náznak činnosti – neošetřená výjimka
Při provádění metody příkaz2
dojde k NEošetřené chybě
try {
příkaz1();
příkaz2();
příkaz3();
}
catch ( xxxException e ) {
příkazProOšetřeníChyby();
}
Ošetření nebylo nalezeno =>
catch (…..
provede se blok finally
a opouští se metoda
finally {
ukončovacíPříkazy();
}
dalšíPříkaz();
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
14
Vyvolání výjimky
public class Xyz implements Comparable
{
public bolean compareTo( Object o )
{
if( !(o instanceOf Xyz) )
throw new ClassCastException (
"\nPokus o porovnání s neporovnatelnou"
+ " instancí " + o );
//Zjištění, kdo je větší
return vysledek;
}
}
► Instanci nemusíme vytvářet až v příkazu throw,
můžeme ji vytvořit kdykoliv před tím a pak mu ji jen předat
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
15
Vaše jistota na trhu IT
Výjimky kontrolované a
nekontrolované
►Hierarchie výjimek
►Pořadí výjimek v blocích catch
►Metody generující výjimky
►Metody třídy Throwable
►Zřetězené výjimky
►Převod kontrolovaných na nekontrolované
Charakteristika
► Výjimky, které jsou potomky třídy RuntimeException
nebo Error označujeme jako nekontrolované (unchecked),
protože překladač nekontroluje, zda je na ně program připraven
► Ostatní výjimky označujeme jako kontrolované (checked),
protože překladač kontroluje dodržení pravidel:
● Každá metoda, která může vyhodit kontrolovanou výjimku,
se musí k této skutečnosti veřejně přihlásit
● Každé použití metody, která může vyhodit kontrolovanou výjimku,
musí být buď uzavřeno v bloku try…catch,
nebo se volající metoda musí přihlásit k tomu,
že může také vyhodit danou kontrolovanou výjimku
► Nekontrolované výjimky ohlašují chyby v programu,
kontrolované výjimky očekávatelné situace,
na jejichž výskyt má být program připraven
a měl by na ně umět reagovat
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
17
Hierarchie výjimek
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
18
Pořadí výjimek v blocích catch
► Třída NumberFormatException
je potomkem třídy RuntimeException
try {
Syntaktická chyba,
......
na druhý blok catch nikdy nedojde
}
catch (RuntimeException e) {
.........
}
Obrácené pořadí bloků catch
catch (NumberFormatException e){
vše vyřeší
........
try {
}
......
}
catch (NumberFormatException e) {
.........
}
catch (RuntimeException e){
........
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
19
Metody generující výjimky
► Java vyžaduje, aby programy, které používají metody
schopné vyvolat kontrolované výjimky,
byly o této schopnosti používaných metod informovány =>
pak vědí, které výjimku musí umět zachytit a ošetřit
► Všechny kontrolované výjimky, které může metoda vyhodit,
musí deklarovat v hlavičce za klíčovým slovem throws
► Deklarace vyhazování nekontrolovaných výjimek není povinná
public void metoda()
throws KontrolovanáVýjimka1,
KontrolovanáVýjimka2
{
// Tělo metody
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
20
Metody třídy Throwable
► String getMessage()
Vrátí zprávu popisující danou výjimku
► String toString()
Vrátí název třídy výjimky následovaný případnou zprávou
► void printStackTrace()
Vytiskne toString() následovaný sadou informací o volající
posloupnosti, která vedla k vzniku výjimky
► Throwable fillInStackTrace()
Připraví nové informace o volací posloupnosti
vedoucí k místu zavolání této metody
► StackTraceElement[] getStackTrace()
Vrátí uchované informace o volací posloupnosti dané výjimky
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
21
Zřetězené výjimky
► V některých situacích je vhodné v rámci ošetření výjimky vyvolat
jinou výjimku, a přitom umožnit zjistit,
která výjimka byla prvotním hybatelem celé akce
► Řada výjimek má mezi svými konstruktory i takové,
které akceptují jako poslední parametr
odkaz na výjimku, jež byla příčinou vyvolání dané výjimky
► Chce-li se program zeptat výjimky na výjimku, která ji způsobila,
použije metodu
public Throwable getCause()
► Ve zprávě o vyvolání výjimky jsou místa, kde byla jedna výjimka
nahrazena jinou, označována textem caused by:
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
22
Ukázka výpisu při zřetězení výjimek
HighLevelException: MidLevelException: LowLevelException
at Junk.a(Junk.java:13)
at Junk.main(Junk.java:4)
Caused by: MidLevelException: LowLevelException
at Junk.c(Junk.java:23)
at Junk.b(Junk.java:17)
at Junk.a(Junk.java:11)
... 1 more
Caused by: LowLevelException
at Junk.e(Junk.java:30)
at Junk.d(Junk.java:27)
at Junk.c(Junk.java:21)
... 3 more
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
23
Převod kontrolovaných na nekontrolované
► Ošetřování kontrolovaných výjimek obtěžuje
► Víme-li, že k dané výjimce nejspíš nedojde
a ošetřujeme-li ji pouze proto, že na tom překladač trvá,
můžeme pro případ, že by k výjimce přece jenom došlo
zaměnit kontrolovanou výjimku za nekontrolovanou
public void prevod( String s ) {
try {
prověř( s );
} catch( Exception ex ) {
throw new RuntimeException( " Neprověřeno! ", ex );
}
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
24
Vaše jistota na trhu IT
Definice vlastních výjimek
►Hierarchie výjimek
►Pořadí výjimek v blocích catch
►Metody generující výjimky
►Metody třídy Throwable
►Vlastní výjimky
►Zásady správného používání výjimek
Definice vlastních výjimek
► Výjimky jsou zcela běžné třídy;
považujeme-li to proto za vhodné, můžeme definovat i vlastní
► Před definicí nové výjimky bychom si měli ujasnit,
bude-li kontrolovaná či nekontrolovaná;
podle toho definujeme jejího předka
► Název výjimek končí dle konvencí slovem Exception
před nímž je naznačena podstata dané výjimky
● IllegalArgumetnException
● NoSuchMethodException
● BadStringOperationException
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
26
Příklad vlastní kontrolované výjimky
public class VelkýPrůšvihException
extends Exception
{
public VelkýPrůšvihException() {};
public VelkýPrůšvihException( String zpráva ) {
super( zpráva );
}
public VelkýPrůšvihException(String zpráva,
Throwable původce ) {
super( zpráva, původce );
}
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
27
Test správného vyhození výjimky
► Na vytvářených programech je třeba otestovat i to,
že v definovaných situacích vyhodí požadovanou výjimku
public void testVyhozeníVýjimky()
{
try {
metodaKteráMáVyhoditVýjimku();
} catch ( VelkýPrůšvihException vpe ) {
return;
}
fail( "Nebyla vyhozena výjimka VelkýPrůšvihException" );
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
28
Zásady správného používání výjimek
1/2
Neignorujte
výjimky
try {
//Nějaký kód
}
catch(Exception e){}
► Výjimky, o nichž víte, že nemohou nastat,
převeďte na nekontrolované pro případ,
že by v budoucích verzích programu nastat mohly
► Při ošetřování výjimek, které nastat mohou,
ale nemají vliv na chod programu,
vložte do těla ošetření alespoň vysvětlující komentář
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
29
Zásady správného používání výjimek
2/2
► Používejte výjimky pouze k ošetření výjimečných stavů
► Kontrolované výjimky používejte u stavů, z nichž se lze zotavit,
jinak použijte výjimky nekontrolované
► Vyhýbejte se zbytečnému používání kontrolovaných výjimek
● Programátory ošetřování kontrolovaných výjimek obtěžuje
a mají pak tendenci je ošetřovat prázdným blokem catch
► Dávejte přednost standardním výjimkám,
vyvolávejte výjimky odpovídající dané abstrakci
● Programátoři by měli z názvu výjimky poznat, co se stalo
● Standardní výjimky mají všeobecně známý význam
► Snažte se o atomičnost selhání; i po vyhození výjimky
by měl být objekt v dobře definovaném stavu
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
30
Zásady správného používání výjimek
3/2
► Doplňujte výjimky zprávami,
výjimka by sama měla poskytnout dostatek informací
a neměla by programátora nutit k podrobnější analýze programu
► Dokumentujte vyvolávané výjimky v dokumentačních
komentářích pomocí značky @throws
► Nedělejte bloky try zbytečně velké,
kód uvnitř těchto bloků se neoptimalizuje
► Umíte-li výjimku v metodě ošetřit, udělejte to
► Detekuje-li se chyba v jedné metodě a má se ošetřit v jiné
(stejné či jiné instance), použijte výjimku.
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
31
Nejčastěji používané výjimky
1/2
► IllegalArgumentException
Byla zadána nepovolená hodnota parametru
● Např. chci nastavit zápornou velikost grafického tvaru
► IllegalStateException
V daném stavu objektu nelze metodu provést
● Např. otevřu soubor, přečtu pár vět, zavřu soubor a chci znovu přečíst větu
► NullPointerException
Byla vyvolána metoda instance, na níž ukazuje prázdný odkaz,
nebo byl předán nepovolený prázdný odkaz v parametru
► ArrayIndexOutOfBoundException
Byly zadány špatné meze pole, buď záporné nebo moc velké
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
32
Nejčastěji používané výjimky
2/2
► ConcurrentModificationException
V průběhu iterace byla změněna struktura kontejneru
● Např. byl do kontejneru přidán prvek
► NumberFormatException
Je požadován špatný převod řetězce na číslo či naopak
● Chci-li např. převést na číslo řetězec, který není číslem
● Častá chyba v metodách String.format či PrintStream.printf
► ClassCastException
Požadované přetypování není možné
► UnsupportedOperationException
Požadovaná operace není podporována
(např. chci přidat prvek do neměnného kontejneru)
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
33
Vaše jistota na trhu IT
Děkuji za pozornost
►Rudolf Pecinovský
http://vyuka.pecinovsky.cz/vse
mail: [email protected]
ICQ: 158 156 600
Slide 22
Vaše jistota na trhu IT
Výjimky
Rudolf Pecinovský
[email protected]
Vaše jistota na trhu IT
Obsah s odkazy
►Výjimky
►Výjimky kontrolované a nekontrolované
►Definice vlastních výjimek
Vaše jistota na trhu IT
Výjimky
►Výjimečné situace v programech
►Ošetření nestandardních situací v Javě
►Zpráva o výjimce
►Klíčová slova
►Činnost
►Vyvolání
Výjimečné situace v programech
► V každém programu je alespoň jedna chyba –
program na ni musí být připraven
► Starší programy
● Program vypsal chybové hlášení a ukončil činnost;
● V některých situacích (válcovací stolice, autopilot, …) nepřijatelné
● Funkce vrátí hodnotu signalizující chybu
● Programátor musí neustále testovat, co funkce vrací
● Knihovna měla pro tyto účely vyhrazenu speciální proměnnou,
do níž se v případě chyby zapsal její kód; nahlédnutím do proměnné
program zjistil kód poslední chyby
● Programátor musí neustále testovat, jaká je v proměnné hodnota
► Některé jazyky (Cobol, PL/1, …) proto přišly s koncepcí
ošetření nestandardních situací
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
4
Ošetření nestandardních situací v Javě
► Výjimečná událost =
problém, který brání dalšímu vykonávání části kódu
► Událost je výjimečná v tom, že na rozdíl od běžných problémů
nemá program k vyřešení situace dost informaci
► Program může při výskytu výjimečné události vyvolat výjimku
► Výjimka (exception)
objekt určený k přenosu informací o nastalém problému
z místa jeho vzniku do místa, kde bude problém řešen
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
5
Postup při vyvolání výjimky
1. Vytvoří se výjimka = objekt typu Throwable
(prakticky vždy instance některého z potomků)
2. Vytvořená výjimka se vyhodí =
přeruší se běh programu v místě, kde výjimka vznikla,
a začne se hledat místo, kde bude daná výjimka ošetřena
3. Ošetření výjimky (handler) by mělo uvést program do stavu,
v němž může jeho vykonávání pokračovat
► Výjimka „probublává“ programem z místa vyhození stále výše
a nenarazí-li cestou nikde na své ošetření,
zachytí ji virtuální stroj, který na standardní chybový výstup
vypíše zprávu o vzniku výjimky
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
6
Systémová zpráva o vzniku výjimky
Zpráva o vzniku výjimky spolu s názvem vlákna,
v němž k výjimce došlo (zde AWT-EventQueue-0)
Popis druhu výjimky (aritmetická výjimka dělení nulou)
Informace o místě, odkud byla volána metoda,
která vyvolala metodu, v níž došlo k vyhození výjimky
Informace o místě, odkud byla volána metoda,
v níž došlo k vyhození výjimky
Úplný název třídy včetně balíčku
Copyright © 2006, Rudolf Pecinovský
Název metody
VŠE – 05
Název souboru se
zdrojovým kódem
Číslo řádku zdrojáku,
kde došlo k výjimce
7
Klíčová slova související s výjimkami
► try (zkus)
Označuje blok kódu, v němž může dojít k výjimce
► throw (hoď)
Příkaz k vyhození výjimky;
musí být následován odkazem na existující instanci
► catch (chyť)
Blok ošetřující výjimku, která je zadána jako parametr
► finally (na konec)
Blok s povinnými závěrečnými akcemi nezávisejícími
na případném vzniku výjimky
► throws (hází)
Uvození seznamu výjimek vyhazovaných danou metodou
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
8
Vyvolání a ošetření výjimky v kódu
try {
//Kód, který může vyvolat výjimky
}
catch( Typ1 id1 ) {
//Ošetření výjimek typu Typ1
}
...
catch( TypN idN ) {
//ošetření výjimek typu TypN
}
finally {
//Kód, který se na závěr VŽDY provede
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
9
Náznak činnosti – řádný průběh
nedojde k vyvolání výjimky
= nedojde k chybě
try {
příkaz1();
příkaz2();
příkaz3();
}
catch ( xxxException e ) {
příkazProOšetřeníChyby();
}
Bloky catch
catch (…..
se přeskočí
finally {
ukončovacíPříkazy();
}
dalšíPříkaz();
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
12
Náznak činnosti – ošetřený výjimka
try {
příkaz1(); Při provádění metody příkaz2
dojde k ošetřené chybě
příkaz2();
příkaz3();
Byla vyhozena výjimka
tohoto typu nebo typu
}
některého z potomků
catch ( xxxException e ) {
příkazProOšetřeníChyby();
}
Ostatní bloky catch
catch (…..
se přeskočí
finally {
ukončovacíPříkazy();
}
dalšíPříkaz();
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
13
Náznak činnosti – neošetřená výjimka
Při provádění metody příkaz2
dojde k NEošetřené chybě
try {
příkaz1();
příkaz2();
příkaz3();
}
catch ( xxxException e ) {
příkazProOšetřeníChyby();
}
Ošetření nebylo nalezeno =>
catch (…..
provede se blok finally
a opouští se metoda
finally {
ukončovacíPříkazy();
}
dalšíPříkaz();
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
14
Vyvolání výjimky
public class Xyz implements Comparable
{
public bolean compareTo( Object o )
{
if( !(o instanceOf Xyz) )
throw new ClassCastException (
"\nPokus o porovnání s neporovnatelnou"
+ " instancí " + o );
//Zjištění, kdo je větší
return vysledek;
}
}
► Instanci nemusíme vytvářet až v příkazu throw,
můžeme ji vytvořit kdykoliv před tím a pak mu ji jen předat
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
15
Vaše jistota na trhu IT
Výjimky kontrolované a
nekontrolované
►Hierarchie výjimek
►Pořadí výjimek v blocích catch
►Metody generující výjimky
►Metody třídy Throwable
►Zřetězené výjimky
►Převod kontrolovaných na nekontrolované
Charakteristika
► Výjimky, které jsou potomky třídy RuntimeException
nebo Error označujeme jako nekontrolované (unchecked),
protože překladač nekontroluje, zda je na ně program připraven
► Ostatní výjimky označujeme jako kontrolované (checked),
protože překladač kontroluje dodržení pravidel:
● Každá metoda, která může vyhodit kontrolovanou výjimku,
se musí k této skutečnosti veřejně přihlásit
● Každé použití metody, která může vyhodit kontrolovanou výjimku,
musí být buď uzavřeno v bloku try…catch,
nebo se volající metoda musí přihlásit k tomu,
že může také vyhodit danou kontrolovanou výjimku
► Nekontrolované výjimky ohlašují chyby v programu,
kontrolované výjimky očekávatelné situace,
na jejichž výskyt má být program připraven
a měl by na ně umět reagovat
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
17
Hierarchie výjimek
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
18
Pořadí výjimek v blocích catch
► Třída NumberFormatException
je potomkem třídy RuntimeException
try {
Syntaktická chyba,
......
na druhý blok catch nikdy nedojde
}
catch (RuntimeException e) {
.........
}
Obrácené pořadí bloků catch
catch (NumberFormatException e){
vše vyřeší
........
try {
}
......
}
catch (NumberFormatException e) {
.........
}
catch (RuntimeException e){
........
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
19
Metody generující výjimky
► Java vyžaduje, aby programy, které používají metody
schopné vyvolat kontrolované výjimky,
byly o této schopnosti používaných metod informovány =>
pak vědí, které výjimku musí umět zachytit a ošetřit
► Všechny kontrolované výjimky, které může metoda vyhodit,
musí deklarovat v hlavičce za klíčovým slovem throws
► Deklarace vyhazování nekontrolovaných výjimek není povinná
public void metoda()
throws KontrolovanáVýjimka1,
KontrolovanáVýjimka2
{
// Tělo metody
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
20
Metody třídy Throwable
► String getMessage()
Vrátí zprávu popisující danou výjimku
► String toString()
Vrátí název třídy výjimky následovaný případnou zprávou
► void printStackTrace()
Vytiskne toString() následovaný sadou informací o volající
posloupnosti, která vedla k vzniku výjimky
► Throwable fillInStackTrace()
Připraví nové informace o volací posloupnosti
vedoucí k místu zavolání této metody
► StackTraceElement[] getStackTrace()
Vrátí uchované informace o volací posloupnosti dané výjimky
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
21
Zřetězené výjimky
► V některých situacích je vhodné v rámci ošetření výjimky vyvolat
jinou výjimku, a přitom umožnit zjistit,
která výjimka byla prvotním hybatelem celé akce
► Řada výjimek má mezi svými konstruktory i takové,
které akceptují jako poslední parametr
odkaz na výjimku, jež byla příčinou vyvolání dané výjimky
► Chce-li se program zeptat výjimky na výjimku, která ji způsobila,
použije metodu
public Throwable getCause()
► Ve zprávě o vyvolání výjimky jsou místa, kde byla jedna výjimka
nahrazena jinou, označována textem caused by:
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
22
Ukázka výpisu při zřetězení výjimek
HighLevelException: MidLevelException: LowLevelException
at Junk.a(Junk.java:13)
at Junk.main(Junk.java:4)
Caused by: MidLevelException: LowLevelException
at Junk.c(Junk.java:23)
at Junk.b(Junk.java:17)
at Junk.a(Junk.java:11)
... 1 more
Caused by: LowLevelException
at Junk.e(Junk.java:30)
at Junk.d(Junk.java:27)
at Junk.c(Junk.java:21)
... 3 more
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
23
Převod kontrolovaných na nekontrolované
► Ošetřování kontrolovaných výjimek obtěžuje
► Víme-li, že k dané výjimce nejspíš nedojde
a ošetřujeme-li ji pouze proto, že na tom překladač trvá,
můžeme pro případ, že by k výjimce přece jenom došlo
zaměnit kontrolovanou výjimku za nekontrolovanou
public void prevod( String s ) {
try {
prověř( s );
} catch( Exception ex ) {
throw new RuntimeException( " Neprověřeno! ", ex );
}
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
24
Vaše jistota na trhu IT
Definice vlastních výjimek
►Hierarchie výjimek
►Pořadí výjimek v blocích catch
►Metody generující výjimky
►Metody třídy Throwable
►Vlastní výjimky
►Zásady správného používání výjimek
Definice vlastních výjimek
► Výjimky jsou zcela běžné třídy;
považujeme-li to proto za vhodné, můžeme definovat i vlastní
► Před definicí nové výjimky bychom si měli ujasnit,
bude-li kontrolovaná či nekontrolovaná;
podle toho definujeme jejího předka
► Název výjimek končí dle konvencí slovem Exception
před nímž je naznačena podstata dané výjimky
● IllegalArgumetnException
● NoSuchMethodException
● BadStringOperationException
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
26
Příklad vlastní kontrolované výjimky
public class VelkýPrůšvihException
extends Exception
{
public VelkýPrůšvihException() {};
public VelkýPrůšvihException( String zpráva ) {
super( zpráva );
}
public VelkýPrůšvihException(String zpráva,
Throwable původce ) {
super( zpráva, původce );
}
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
27
Test správného vyhození výjimky
► Na vytvářených programech je třeba otestovat i to,
že v definovaných situacích vyhodí požadovanou výjimku
public void testVyhozeníVýjimky()
{
try {
metodaKteráMáVyhoditVýjimku();
} catch ( VelkýPrůšvihException vpe ) {
return;
}
fail( "Nebyla vyhozena výjimka VelkýPrůšvihException" );
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
28
Zásady správného používání výjimek
1/2
Neignorujte
výjimky
try {
//Nějaký kód
}
catch(Exception e){}
► Výjimky, o nichž víte, že nemohou nastat,
převeďte na nekontrolované pro případ,
že by v budoucích verzích programu nastat mohly
► Při ošetřování výjimek, které nastat mohou,
ale nemají vliv na chod programu,
vložte do těla ošetření alespoň vysvětlující komentář
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
29
Zásady správného používání výjimek
2/2
► Používejte výjimky pouze k ošetření výjimečných stavů
► Kontrolované výjimky používejte u stavů, z nichž se lze zotavit,
jinak použijte výjimky nekontrolované
► Vyhýbejte se zbytečnému používání kontrolovaných výjimek
● Programátory ošetřování kontrolovaných výjimek obtěžuje
a mají pak tendenci je ošetřovat prázdným blokem catch
► Dávejte přednost standardním výjimkám,
vyvolávejte výjimky odpovídající dané abstrakci
● Programátoři by měli z názvu výjimky poznat, co se stalo
● Standardní výjimky mají všeobecně známý význam
► Snažte se o atomičnost selhání; i po vyhození výjimky
by měl být objekt v dobře definovaném stavu
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
30
Zásady správného používání výjimek
3/2
► Doplňujte výjimky zprávami,
výjimka by sama měla poskytnout dostatek informací
a neměla by programátora nutit k podrobnější analýze programu
► Dokumentujte vyvolávané výjimky v dokumentačních
komentářích pomocí značky @throws
► Nedělejte bloky try zbytečně velké,
kód uvnitř těchto bloků se neoptimalizuje
► Umíte-li výjimku v metodě ošetřit, udělejte to
► Detekuje-li se chyba v jedné metodě a má se ošetřit v jiné
(stejné či jiné instance), použijte výjimku.
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
31
Nejčastěji používané výjimky
1/2
► IllegalArgumentException
Byla zadána nepovolená hodnota parametru
● Např. chci nastavit zápornou velikost grafického tvaru
► IllegalStateException
V daném stavu objektu nelze metodu provést
● Např. otevřu soubor, přečtu pár vět, zavřu soubor a chci znovu přečíst větu
► NullPointerException
Byla vyvolána metoda instance, na níž ukazuje prázdný odkaz,
nebo byl předán nepovolený prázdný odkaz v parametru
► ArrayIndexOutOfBoundException
Byly zadány špatné meze pole, buď záporné nebo moc velké
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
32
Nejčastěji používané výjimky
2/2
► ConcurrentModificationException
V průběhu iterace byla změněna struktura kontejneru
● Např. byl do kontejneru přidán prvek
► NumberFormatException
Je požadován špatný převod řetězce na číslo či naopak
● Chci-li např. převést na číslo řetězec, který není číslem
● Častá chyba v metodách String.format či PrintStream.printf
► ClassCastException
Požadované přetypování není možné
► UnsupportedOperationException
Požadovaná operace není podporována
(např. chci přidat prvek do neměnného kontejneru)
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
33
Vaše jistota na trhu IT
Děkuji za pozornost
►Rudolf Pecinovský
http://vyuka.pecinovsky.cz/vse
mail: [email protected]
ICQ: 158 156 600
Slide 23
Vaše jistota na trhu IT
Výjimky
Rudolf Pecinovský
[email protected]
Vaše jistota na trhu IT
Obsah s odkazy
►Výjimky
►Výjimky kontrolované a nekontrolované
►Definice vlastních výjimek
Vaše jistota na trhu IT
Výjimky
►Výjimečné situace v programech
►Ošetření nestandardních situací v Javě
►Zpráva o výjimce
►Klíčová slova
►Činnost
►Vyvolání
Výjimečné situace v programech
► V každém programu je alespoň jedna chyba –
program na ni musí být připraven
► Starší programy
● Program vypsal chybové hlášení a ukončil činnost;
● V některých situacích (válcovací stolice, autopilot, …) nepřijatelné
● Funkce vrátí hodnotu signalizující chybu
● Programátor musí neustále testovat, co funkce vrací
● Knihovna měla pro tyto účely vyhrazenu speciální proměnnou,
do níž se v případě chyby zapsal její kód; nahlédnutím do proměnné
program zjistil kód poslední chyby
● Programátor musí neustále testovat, jaká je v proměnné hodnota
► Některé jazyky (Cobol, PL/1, …) proto přišly s koncepcí
ošetření nestandardních situací
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
4
Ošetření nestandardních situací v Javě
► Výjimečná událost =
problém, který brání dalšímu vykonávání části kódu
► Událost je výjimečná v tom, že na rozdíl od běžných problémů
nemá program k vyřešení situace dost informaci
► Program může při výskytu výjimečné události vyvolat výjimku
► Výjimka (exception)
objekt určený k přenosu informací o nastalém problému
z místa jeho vzniku do místa, kde bude problém řešen
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
5
Postup při vyvolání výjimky
1. Vytvoří se výjimka = objekt typu Throwable
(prakticky vždy instance některého z potomků)
2. Vytvořená výjimka se vyhodí =
přeruší se běh programu v místě, kde výjimka vznikla,
a začne se hledat místo, kde bude daná výjimka ošetřena
3. Ošetření výjimky (handler) by mělo uvést program do stavu,
v němž může jeho vykonávání pokračovat
► Výjimka „probublává“ programem z místa vyhození stále výše
a nenarazí-li cestou nikde na své ošetření,
zachytí ji virtuální stroj, který na standardní chybový výstup
vypíše zprávu o vzniku výjimky
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
6
Systémová zpráva o vzniku výjimky
Zpráva o vzniku výjimky spolu s názvem vlákna,
v němž k výjimce došlo (zde AWT-EventQueue-0)
Popis druhu výjimky (aritmetická výjimka dělení nulou)
Informace o místě, odkud byla volána metoda,
která vyvolala metodu, v níž došlo k vyhození výjimky
Informace o místě, odkud byla volána metoda,
v níž došlo k vyhození výjimky
Úplný název třídy včetně balíčku
Copyright © 2006, Rudolf Pecinovský
Název metody
VŠE – 05
Název souboru se
zdrojovým kódem
Číslo řádku zdrojáku,
kde došlo k výjimce
7
Klíčová slova související s výjimkami
► try (zkus)
Označuje blok kódu, v němž může dojít k výjimce
► throw (hoď)
Příkaz k vyhození výjimky;
musí být následován odkazem na existující instanci
► catch (chyť)
Blok ošetřující výjimku, která je zadána jako parametr
► finally (na konec)
Blok s povinnými závěrečnými akcemi nezávisejícími
na případném vzniku výjimky
► throws (hází)
Uvození seznamu výjimek vyhazovaných danou metodou
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
8
Vyvolání a ošetření výjimky v kódu
try {
//Kód, který může vyvolat výjimky
}
catch( Typ1 id1 ) {
//Ošetření výjimek typu Typ1
}
...
catch( TypN idN ) {
//ošetření výjimek typu TypN
}
finally {
//Kód, který se na závěr VŽDY provede
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
9
Náznak činnosti – řádný průběh
nedojde k vyvolání výjimky
= nedojde k chybě
try {
příkaz1();
příkaz2();
příkaz3();
}
catch ( xxxException e ) {
příkazProOšetřeníChyby();
}
Bloky catch
catch (…..
se přeskočí
finally {
ukončovacíPříkazy();
}
dalšíPříkaz();
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
12
Náznak činnosti – ošetřený výjimka
try {
příkaz1(); Při provádění metody příkaz2
dojde k ošetřené chybě
příkaz2();
příkaz3();
Byla vyhozena výjimka
tohoto typu nebo typu
}
některého z potomků
catch ( xxxException e ) {
příkazProOšetřeníChyby();
}
Ostatní bloky catch
catch (…..
se přeskočí
finally {
ukončovacíPříkazy();
}
dalšíPříkaz();
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
13
Náznak činnosti – neošetřená výjimka
Při provádění metody příkaz2
dojde k NEošetřené chybě
try {
příkaz1();
příkaz2();
příkaz3();
}
catch ( xxxException e ) {
příkazProOšetřeníChyby();
}
Ošetření nebylo nalezeno =>
catch (…..
provede se blok finally
a opouští se metoda
finally {
ukončovacíPříkazy();
}
dalšíPříkaz();
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
14
Vyvolání výjimky
public class Xyz implements Comparable
{
public bolean compareTo( Object o )
{
if( !(o instanceOf Xyz) )
throw new ClassCastException (
"\nPokus o porovnání s neporovnatelnou"
+ " instancí " + o );
//Zjištění, kdo je větší
return vysledek;
}
}
► Instanci nemusíme vytvářet až v příkazu throw,
můžeme ji vytvořit kdykoliv před tím a pak mu ji jen předat
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
15
Vaše jistota na trhu IT
Výjimky kontrolované a
nekontrolované
►Hierarchie výjimek
►Pořadí výjimek v blocích catch
►Metody generující výjimky
►Metody třídy Throwable
►Zřetězené výjimky
►Převod kontrolovaných na nekontrolované
Charakteristika
► Výjimky, které jsou potomky třídy RuntimeException
nebo Error označujeme jako nekontrolované (unchecked),
protože překladač nekontroluje, zda je na ně program připraven
► Ostatní výjimky označujeme jako kontrolované (checked),
protože překladač kontroluje dodržení pravidel:
● Každá metoda, která může vyhodit kontrolovanou výjimku,
se musí k této skutečnosti veřejně přihlásit
● Každé použití metody, která může vyhodit kontrolovanou výjimku,
musí být buď uzavřeno v bloku try…catch,
nebo se volající metoda musí přihlásit k tomu,
že může také vyhodit danou kontrolovanou výjimku
► Nekontrolované výjimky ohlašují chyby v programu,
kontrolované výjimky očekávatelné situace,
na jejichž výskyt má být program připraven
a měl by na ně umět reagovat
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
17
Hierarchie výjimek
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
18
Pořadí výjimek v blocích catch
► Třída NumberFormatException
je potomkem třídy RuntimeException
try {
Syntaktická chyba,
......
na druhý blok catch nikdy nedojde
}
catch (RuntimeException e) {
.........
}
Obrácené pořadí bloků catch
catch (NumberFormatException e){
vše vyřeší
........
try {
}
......
}
catch (NumberFormatException e) {
.........
}
catch (RuntimeException e){
........
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
19
Metody generující výjimky
► Java vyžaduje, aby programy, které používají metody
schopné vyvolat kontrolované výjimky,
byly o této schopnosti používaných metod informovány =>
pak vědí, které výjimku musí umět zachytit a ošetřit
► Všechny kontrolované výjimky, které může metoda vyhodit,
musí deklarovat v hlavičce za klíčovým slovem throws
► Deklarace vyhazování nekontrolovaných výjimek není povinná
public void metoda()
throws KontrolovanáVýjimka1,
KontrolovanáVýjimka2
{
// Tělo metody
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
20
Metody třídy Throwable
► String getMessage()
Vrátí zprávu popisující danou výjimku
► String toString()
Vrátí název třídy výjimky následovaný případnou zprávou
► void printStackTrace()
Vytiskne toString() následovaný sadou informací o volající
posloupnosti, která vedla k vzniku výjimky
► Throwable fillInStackTrace()
Připraví nové informace o volací posloupnosti
vedoucí k místu zavolání této metody
► StackTraceElement[] getStackTrace()
Vrátí uchované informace o volací posloupnosti dané výjimky
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
21
Zřetězené výjimky
► V některých situacích je vhodné v rámci ošetření výjimky vyvolat
jinou výjimku, a přitom umožnit zjistit,
která výjimka byla prvotním hybatelem celé akce
► Řada výjimek má mezi svými konstruktory i takové,
které akceptují jako poslední parametr
odkaz na výjimku, jež byla příčinou vyvolání dané výjimky
► Chce-li se program zeptat výjimky na výjimku, která ji způsobila,
použije metodu
public Throwable getCause()
► Ve zprávě o vyvolání výjimky jsou místa, kde byla jedna výjimka
nahrazena jinou, označována textem caused by:
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
22
Ukázka výpisu při zřetězení výjimek
HighLevelException: MidLevelException: LowLevelException
at Junk.a(Junk.java:13)
at Junk.main(Junk.java:4)
Caused by: MidLevelException: LowLevelException
at Junk.c(Junk.java:23)
at Junk.b(Junk.java:17)
at Junk.a(Junk.java:11)
... 1 more
Caused by: LowLevelException
at Junk.e(Junk.java:30)
at Junk.d(Junk.java:27)
at Junk.c(Junk.java:21)
... 3 more
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
23
Převod kontrolovaných na nekontrolované
► Ošetřování kontrolovaných výjimek obtěžuje
► Víme-li, že k dané výjimce nejspíš nedojde
a ošetřujeme-li ji pouze proto, že na tom překladač trvá,
můžeme pro případ, že by k výjimce přece jenom došlo
zaměnit kontrolovanou výjimku za nekontrolovanou
public void prevod( String s ) {
try {
prověř( s );
} catch( Exception ex ) {
throw new RuntimeException( " Neprověřeno! ", ex );
}
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
24
Vaše jistota na trhu IT
Definice vlastních výjimek
►Hierarchie výjimek
►Pořadí výjimek v blocích catch
►Metody generující výjimky
►Metody třídy Throwable
►Vlastní výjimky
►Zásady správného používání výjimek
Definice vlastních výjimek
► Výjimky jsou zcela běžné třídy;
považujeme-li to proto za vhodné, můžeme definovat i vlastní
► Před definicí nové výjimky bychom si měli ujasnit,
bude-li kontrolovaná či nekontrolovaná;
podle toho definujeme jejího předka
► Název výjimek končí dle konvencí slovem Exception
před nímž je naznačena podstata dané výjimky
● IllegalArgumetnException
● NoSuchMethodException
● BadStringOperationException
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
26
Příklad vlastní kontrolované výjimky
public class VelkýPrůšvihException
extends Exception
{
public VelkýPrůšvihException() {};
public VelkýPrůšvihException( String zpráva ) {
super( zpráva );
}
public VelkýPrůšvihException(String zpráva,
Throwable původce ) {
super( zpráva, původce );
}
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
27
Test správného vyhození výjimky
► Na vytvářených programech je třeba otestovat i to,
že v definovaných situacích vyhodí požadovanou výjimku
public void testVyhozeníVýjimky()
{
try {
metodaKteráMáVyhoditVýjimku();
} catch ( VelkýPrůšvihException vpe ) {
return;
}
fail( "Nebyla vyhozena výjimka VelkýPrůšvihException" );
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
28
Zásady správného používání výjimek
1/2
Neignorujte
výjimky
try {
//Nějaký kód
}
catch(Exception e){}
► Výjimky, o nichž víte, že nemohou nastat,
převeďte na nekontrolované pro případ,
že by v budoucích verzích programu nastat mohly
► Při ošetřování výjimek, které nastat mohou,
ale nemají vliv na chod programu,
vložte do těla ošetření alespoň vysvětlující komentář
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
29
Zásady správného používání výjimek
2/2
► Používejte výjimky pouze k ošetření výjimečných stavů
► Kontrolované výjimky používejte u stavů, z nichž se lze zotavit,
jinak použijte výjimky nekontrolované
► Vyhýbejte se zbytečnému používání kontrolovaných výjimek
● Programátory ošetřování kontrolovaných výjimek obtěžuje
a mají pak tendenci je ošetřovat prázdným blokem catch
► Dávejte přednost standardním výjimkám,
vyvolávejte výjimky odpovídající dané abstrakci
● Programátoři by měli z názvu výjimky poznat, co se stalo
● Standardní výjimky mají všeobecně známý význam
► Snažte se o atomičnost selhání; i po vyhození výjimky
by měl být objekt v dobře definovaném stavu
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
30
Zásady správného používání výjimek
3/2
► Doplňujte výjimky zprávami,
výjimka by sama měla poskytnout dostatek informací
a neměla by programátora nutit k podrobnější analýze programu
► Dokumentujte vyvolávané výjimky v dokumentačních
komentářích pomocí značky @throws
► Nedělejte bloky try zbytečně velké,
kód uvnitř těchto bloků se neoptimalizuje
► Umíte-li výjimku v metodě ošetřit, udělejte to
► Detekuje-li se chyba v jedné metodě a má se ošetřit v jiné
(stejné či jiné instance), použijte výjimku.
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
31
Nejčastěji používané výjimky
1/2
► IllegalArgumentException
Byla zadána nepovolená hodnota parametru
● Např. chci nastavit zápornou velikost grafického tvaru
► IllegalStateException
V daném stavu objektu nelze metodu provést
● Např. otevřu soubor, přečtu pár vět, zavřu soubor a chci znovu přečíst větu
► NullPointerException
Byla vyvolána metoda instance, na níž ukazuje prázdný odkaz,
nebo byl předán nepovolený prázdný odkaz v parametru
► ArrayIndexOutOfBoundException
Byly zadány špatné meze pole, buď záporné nebo moc velké
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
32
Nejčastěji používané výjimky
2/2
► ConcurrentModificationException
V průběhu iterace byla změněna struktura kontejneru
● Např. byl do kontejneru přidán prvek
► NumberFormatException
Je požadován špatný převod řetězce na číslo či naopak
● Chci-li např. převést na číslo řetězec, který není číslem
● Častá chyba v metodách String.format či PrintStream.printf
► ClassCastException
Požadované přetypování není možné
► UnsupportedOperationException
Požadovaná operace není podporována
(např. chci přidat prvek do neměnného kontejneru)
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
33
Vaše jistota na trhu IT
Děkuji za pozornost
►Rudolf Pecinovský
http://vyuka.pecinovsky.cz/vse
mail: [email protected]
ICQ: 158 156 600
Slide 24
Vaše jistota na trhu IT
Výjimky
Rudolf Pecinovský
[email protected]
Vaše jistota na trhu IT
Obsah s odkazy
►Výjimky
►Výjimky kontrolované a nekontrolované
►Definice vlastních výjimek
Vaše jistota na trhu IT
Výjimky
►Výjimečné situace v programech
►Ošetření nestandardních situací v Javě
►Zpráva o výjimce
►Klíčová slova
►Činnost
►Vyvolání
Výjimečné situace v programech
► V každém programu je alespoň jedna chyba –
program na ni musí být připraven
► Starší programy
● Program vypsal chybové hlášení a ukončil činnost;
● V některých situacích (válcovací stolice, autopilot, …) nepřijatelné
● Funkce vrátí hodnotu signalizující chybu
● Programátor musí neustále testovat, co funkce vrací
● Knihovna měla pro tyto účely vyhrazenu speciální proměnnou,
do níž se v případě chyby zapsal její kód; nahlédnutím do proměnné
program zjistil kód poslední chyby
● Programátor musí neustále testovat, jaká je v proměnné hodnota
► Některé jazyky (Cobol, PL/1, …) proto přišly s koncepcí
ošetření nestandardních situací
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
4
Ošetření nestandardních situací v Javě
► Výjimečná událost =
problém, který brání dalšímu vykonávání části kódu
► Událost je výjimečná v tom, že na rozdíl od běžných problémů
nemá program k vyřešení situace dost informaci
► Program může při výskytu výjimečné události vyvolat výjimku
► Výjimka (exception)
objekt určený k přenosu informací o nastalém problému
z místa jeho vzniku do místa, kde bude problém řešen
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
5
Postup při vyvolání výjimky
1. Vytvoří se výjimka = objekt typu Throwable
(prakticky vždy instance některého z potomků)
2. Vytvořená výjimka se vyhodí =
přeruší se běh programu v místě, kde výjimka vznikla,
a začne se hledat místo, kde bude daná výjimka ošetřena
3. Ošetření výjimky (handler) by mělo uvést program do stavu,
v němž může jeho vykonávání pokračovat
► Výjimka „probublává“ programem z místa vyhození stále výše
a nenarazí-li cestou nikde na své ošetření,
zachytí ji virtuální stroj, který na standardní chybový výstup
vypíše zprávu o vzniku výjimky
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
6
Systémová zpráva o vzniku výjimky
Zpráva o vzniku výjimky spolu s názvem vlákna,
v němž k výjimce došlo (zde AWT-EventQueue-0)
Popis druhu výjimky (aritmetická výjimka dělení nulou)
Informace o místě, odkud byla volána metoda,
která vyvolala metodu, v níž došlo k vyhození výjimky
Informace o místě, odkud byla volána metoda,
v níž došlo k vyhození výjimky
Úplný název třídy včetně balíčku
Copyright © 2006, Rudolf Pecinovský
Název metody
VŠE – 05
Název souboru se
zdrojovým kódem
Číslo řádku zdrojáku,
kde došlo k výjimce
7
Klíčová slova související s výjimkami
► try (zkus)
Označuje blok kódu, v němž může dojít k výjimce
► throw (hoď)
Příkaz k vyhození výjimky;
musí být následován odkazem na existující instanci
► catch (chyť)
Blok ošetřující výjimku, která je zadána jako parametr
► finally (na konec)
Blok s povinnými závěrečnými akcemi nezávisejícími
na případném vzniku výjimky
► throws (hází)
Uvození seznamu výjimek vyhazovaných danou metodou
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
8
Vyvolání a ošetření výjimky v kódu
try {
//Kód, který může vyvolat výjimky
}
catch( Typ1 id1 ) {
//Ošetření výjimek typu Typ1
}
...
catch( TypN idN ) {
//ošetření výjimek typu TypN
}
finally {
//Kód, který se na závěr VŽDY provede
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
9
Náznak činnosti – řádný průběh
nedojde k vyvolání výjimky
= nedojde k chybě
try {
příkaz1();
příkaz2();
příkaz3();
}
catch ( xxxException e ) {
příkazProOšetřeníChyby();
}
Bloky catch
catch (…..
se přeskočí
finally {
ukončovacíPříkazy();
}
dalšíPříkaz();
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
12
Náznak činnosti – ošetřený výjimka
try {
příkaz1(); Při provádění metody příkaz2
dojde k ošetřené chybě
příkaz2();
příkaz3();
Byla vyhozena výjimka
tohoto typu nebo typu
}
některého z potomků
catch ( xxxException e ) {
příkazProOšetřeníChyby();
}
Ostatní bloky catch
catch (…..
se přeskočí
finally {
ukončovacíPříkazy();
}
dalšíPříkaz();
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
13
Náznak činnosti – neošetřená výjimka
Při provádění metody příkaz2
dojde k NEošetřené chybě
try {
příkaz1();
příkaz2();
příkaz3();
}
catch ( xxxException e ) {
příkazProOšetřeníChyby();
}
Ošetření nebylo nalezeno =>
catch (…..
provede se blok finally
a opouští se metoda
finally {
ukončovacíPříkazy();
}
dalšíPříkaz();
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
14
Vyvolání výjimky
public class Xyz implements Comparable
{
public bolean compareTo( Object o )
{
if( !(o instanceOf Xyz) )
throw new ClassCastException (
"\nPokus o porovnání s neporovnatelnou"
+ " instancí " + o );
//Zjištění, kdo je větší
return vysledek;
}
}
► Instanci nemusíme vytvářet až v příkazu throw,
můžeme ji vytvořit kdykoliv před tím a pak mu ji jen předat
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
15
Vaše jistota na trhu IT
Výjimky kontrolované a
nekontrolované
►Hierarchie výjimek
►Pořadí výjimek v blocích catch
►Metody generující výjimky
►Metody třídy Throwable
►Zřetězené výjimky
►Převod kontrolovaných na nekontrolované
Charakteristika
► Výjimky, které jsou potomky třídy RuntimeException
nebo Error označujeme jako nekontrolované (unchecked),
protože překladač nekontroluje, zda je na ně program připraven
► Ostatní výjimky označujeme jako kontrolované (checked),
protože překladač kontroluje dodržení pravidel:
● Každá metoda, která může vyhodit kontrolovanou výjimku,
se musí k této skutečnosti veřejně přihlásit
● Každé použití metody, která může vyhodit kontrolovanou výjimku,
musí být buď uzavřeno v bloku try…catch,
nebo se volající metoda musí přihlásit k tomu,
že může také vyhodit danou kontrolovanou výjimku
► Nekontrolované výjimky ohlašují chyby v programu,
kontrolované výjimky očekávatelné situace,
na jejichž výskyt má být program připraven
a měl by na ně umět reagovat
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
17
Hierarchie výjimek
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
18
Pořadí výjimek v blocích catch
► Třída NumberFormatException
je potomkem třídy RuntimeException
try {
Syntaktická chyba,
......
na druhý blok catch nikdy nedojde
}
catch (RuntimeException e) {
.........
}
Obrácené pořadí bloků catch
catch (NumberFormatException e){
vše vyřeší
........
try {
}
......
}
catch (NumberFormatException e) {
.........
}
catch (RuntimeException e){
........
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
19
Metody generující výjimky
► Java vyžaduje, aby programy, které používají metody
schopné vyvolat kontrolované výjimky,
byly o této schopnosti používaných metod informovány =>
pak vědí, které výjimku musí umět zachytit a ošetřit
► Všechny kontrolované výjimky, které může metoda vyhodit,
musí deklarovat v hlavičce za klíčovým slovem throws
► Deklarace vyhazování nekontrolovaných výjimek není povinná
public void metoda()
throws KontrolovanáVýjimka1,
KontrolovanáVýjimka2
{
// Tělo metody
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
20
Metody třídy Throwable
► String getMessage()
Vrátí zprávu popisující danou výjimku
► String toString()
Vrátí název třídy výjimky následovaný případnou zprávou
► void printStackTrace()
Vytiskne toString() následovaný sadou informací o volající
posloupnosti, která vedla k vzniku výjimky
► Throwable fillInStackTrace()
Připraví nové informace o volací posloupnosti
vedoucí k místu zavolání této metody
► StackTraceElement[] getStackTrace()
Vrátí uchované informace o volací posloupnosti dané výjimky
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
21
Zřetězené výjimky
► V některých situacích je vhodné v rámci ošetření výjimky vyvolat
jinou výjimku, a přitom umožnit zjistit,
která výjimka byla prvotním hybatelem celé akce
► Řada výjimek má mezi svými konstruktory i takové,
které akceptují jako poslední parametr
odkaz na výjimku, jež byla příčinou vyvolání dané výjimky
► Chce-li se program zeptat výjimky na výjimku, která ji způsobila,
použije metodu
public Throwable getCause()
► Ve zprávě o vyvolání výjimky jsou místa, kde byla jedna výjimka
nahrazena jinou, označována textem caused by:
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
22
Ukázka výpisu při zřetězení výjimek
HighLevelException: MidLevelException: LowLevelException
at Junk.a(Junk.java:13)
at Junk.main(Junk.java:4)
Caused by: MidLevelException: LowLevelException
at Junk.c(Junk.java:23)
at Junk.b(Junk.java:17)
at Junk.a(Junk.java:11)
... 1 more
Caused by: LowLevelException
at Junk.e(Junk.java:30)
at Junk.d(Junk.java:27)
at Junk.c(Junk.java:21)
... 3 more
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
23
Převod kontrolovaných na nekontrolované
► Ošetřování kontrolovaných výjimek obtěžuje
► Víme-li, že k dané výjimce nejspíš nedojde
a ošetřujeme-li ji pouze proto, že na tom překladač trvá,
můžeme pro případ, že by k výjimce přece jenom došlo
zaměnit kontrolovanou výjimku za nekontrolovanou
public void prevod( String s ) {
try {
prověř( s );
} catch( Exception ex ) {
throw new RuntimeException( " Neprověřeno! ", ex );
}
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
24
Vaše jistota na trhu IT
Definice vlastních výjimek
►Hierarchie výjimek
►Pořadí výjimek v blocích catch
►Metody generující výjimky
►Metody třídy Throwable
►Vlastní výjimky
►Zásady správného používání výjimek
Definice vlastních výjimek
► Výjimky jsou zcela běžné třídy;
považujeme-li to proto za vhodné, můžeme definovat i vlastní
► Před definicí nové výjimky bychom si měli ujasnit,
bude-li kontrolovaná či nekontrolovaná;
podle toho definujeme jejího předka
► Název výjimek končí dle konvencí slovem Exception
před nímž je naznačena podstata dané výjimky
● IllegalArgumetnException
● NoSuchMethodException
● BadStringOperationException
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
26
Příklad vlastní kontrolované výjimky
public class VelkýPrůšvihException
extends Exception
{
public VelkýPrůšvihException() {};
public VelkýPrůšvihException( String zpráva ) {
super( zpráva );
}
public VelkýPrůšvihException(String zpráva,
Throwable původce ) {
super( zpráva, původce );
}
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
27
Test správného vyhození výjimky
► Na vytvářených programech je třeba otestovat i to,
že v definovaných situacích vyhodí požadovanou výjimku
public void testVyhozeníVýjimky()
{
try {
metodaKteráMáVyhoditVýjimku();
} catch ( VelkýPrůšvihException vpe ) {
return;
}
fail( "Nebyla vyhozena výjimka VelkýPrůšvihException" );
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
28
Zásady správného používání výjimek
1/2
Neignorujte
výjimky
try {
//Nějaký kód
}
catch(Exception e){}
► Výjimky, o nichž víte, že nemohou nastat,
převeďte na nekontrolované pro případ,
že by v budoucích verzích programu nastat mohly
► Při ošetřování výjimek, které nastat mohou,
ale nemají vliv na chod programu,
vložte do těla ošetření alespoň vysvětlující komentář
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
29
Zásady správného používání výjimek
2/2
► Používejte výjimky pouze k ošetření výjimečných stavů
► Kontrolované výjimky používejte u stavů, z nichž se lze zotavit,
jinak použijte výjimky nekontrolované
► Vyhýbejte se zbytečnému používání kontrolovaných výjimek
● Programátory ošetřování kontrolovaných výjimek obtěžuje
a mají pak tendenci je ošetřovat prázdným blokem catch
► Dávejte přednost standardním výjimkám,
vyvolávejte výjimky odpovídající dané abstrakci
● Programátoři by měli z názvu výjimky poznat, co se stalo
● Standardní výjimky mají všeobecně známý význam
► Snažte se o atomičnost selhání; i po vyhození výjimky
by měl být objekt v dobře definovaném stavu
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
30
Zásady správného používání výjimek
3/2
► Doplňujte výjimky zprávami,
výjimka by sama měla poskytnout dostatek informací
a neměla by programátora nutit k podrobnější analýze programu
► Dokumentujte vyvolávané výjimky v dokumentačních
komentářích pomocí značky @throws
► Nedělejte bloky try zbytečně velké,
kód uvnitř těchto bloků se neoptimalizuje
► Umíte-li výjimku v metodě ošetřit, udělejte to
► Detekuje-li se chyba v jedné metodě a má se ošetřit v jiné
(stejné či jiné instance), použijte výjimku.
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
31
Nejčastěji používané výjimky
1/2
► IllegalArgumentException
Byla zadána nepovolená hodnota parametru
● Např. chci nastavit zápornou velikost grafického tvaru
► IllegalStateException
V daném stavu objektu nelze metodu provést
● Např. otevřu soubor, přečtu pár vět, zavřu soubor a chci znovu přečíst větu
► NullPointerException
Byla vyvolána metoda instance, na níž ukazuje prázdný odkaz,
nebo byl předán nepovolený prázdný odkaz v parametru
► ArrayIndexOutOfBoundException
Byly zadány špatné meze pole, buď záporné nebo moc velké
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
32
Nejčastěji používané výjimky
2/2
► ConcurrentModificationException
V průběhu iterace byla změněna struktura kontejneru
● Např. byl do kontejneru přidán prvek
► NumberFormatException
Je požadován špatný převod řetězce na číslo či naopak
● Chci-li např. převést na číslo řetězec, který není číslem
● Častá chyba v metodách String.format či PrintStream.printf
► ClassCastException
Požadované přetypování není možné
► UnsupportedOperationException
Požadovaná operace není podporována
(např. chci přidat prvek do neměnného kontejneru)
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
33
Vaše jistota na trhu IT
Děkuji za pozornost
►Rudolf Pecinovský
http://vyuka.pecinovsky.cz/vse
mail: [email protected]
ICQ: 158 156 600
Slide 25
Vaše jistota na trhu IT
Výjimky
Rudolf Pecinovský
[email protected]
Vaše jistota na trhu IT
Obsah s odkazy
►Výjimky
►Výjimky kontrolované a nekontrolované
►Definice vlastních výjimek
Vaše jistota na trhu IT
Výjimky
►Výjimečné situace v programech
►Ošetření nestandardních situací v Javě
►Zpráva o výjimce
►Klíčová slova
►Činnost
►Vyvolání
Výjimečné situace v programech
► V každém programu je alespoň jedna chyba –
program na ni musí být připraven
► Starší programy
● Program vypsal chybové hlášení a ukončil činnost;
● V některých situacích (válcovací stolice, autopilot, …) nepřijatelné
● Funkce vrátí hodnotu signalizující chybu
● Programátor musí neustále testovat, co funkce vrací
● Knihovna měla pro tyto účely vyhrazenu speciální proměnnou,
do níž se v případě chyby zapsal její kód; nahlédnutím do proměnné
program zjistil kód poslední chyby
● Programátor musí neustále testovat, jaká je v proměnné hodnota
► Některé jazyky (Cobol, PL/1, …) proto přišly s koncepcí
ošetření nestandardních situací
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
4
Ošetření nestandardních situací v Javě
► Výjimečná událost =
problém, který brání dalšímu vykonávání části kódu
► Událost je výjimečná v tom, že na rozdíl od běžných problémů
nemá program k vyřešení situace dost informaci
► Program může při výskytu výjimečné události vyvolat výjimku
► Výjimka (exception)
objekt určený k přenosu informací o nastalém problému
z místa jeho vzniku do místa, kde bude problém řešen
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
5
Postup při vyvolání výjimky
1. Vytvoří se výjimka = objekt typu Throwable
(prakticky vždy instance některého z potomků)
2. Vytvořená výjimka se vyhodí =
přeruší se běh programu v místě, kde výjimka vznikla,
a začne se hledat místo, kde bude daná výjimka ošetřena
3. Ošetření výjimky (handler) by mělo uvést program do stavu,
v němž může jeho vykonávání pokračovat
► Výjimka „probublává“ programem z místa vyhození stále výše
a nenarazí-li cestou nikde na své ošetření,
zachytí ji virtuální stroj, který na standardní chybový výstup
vypíše zprávu o vzniku výjimky
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
6
Systémová zpráva o vzniku výjimky
Zpráva o vzniku výjimky spolu s názvem vlákna,
v němž k výjimce došlo (zde AWT-EventQueue-0)
Popis druhu výjimky (aritmetická výjimka dělení nulou)
Informace o místě, odkud byla volána metoda,
která vyvolala metodu, v níž došlo k vyhození výjimky
Informace o místě, odkud byla volána metoda,
v níž došlo k vyhození výjimky
Úplný název třídy včetně balíčku
Copyright © 2006, Rudolf Pecinovský
Název metody
VŠE – 05
Název souboru se
zdrojovým kódem
Číslo řádku zdrojáku,
kde došlo k výjimce
7
Klíčová slova související s výjimkami
► try (zkus)
Označuje blok kódu, v němž může dojít k výjimce
► throw (hoď)
Příkaz k vyhození výjimky;
musí být následován odkazem na existující instanci
► catch (chyť)
Blok ošetřující výjimku, která je zadána jako parametr
► finally (na konec)
Blok s povinnými závěrečnými akcemi nezávisejícími
na případném vzniku výjimky
► throws (hází)
Uvození seznamu výjimek vyhazovaných danou metodou
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
8
Vyvolání a ošetření výjimky v kódu
try {
//Kód, který může vyvolat výjimky
}
catch( Typ1 id1 ) {
//Ošetření výjimek typu Typ1
}
...
catch( TypN idN ) {
//ošetření výjimek typu TypN
}
finally {
//Kód, který se na závěr VŽDY provede
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
9
Náznak činnosti – řádný průběh
nedojde k vyvolání výjimky
= nedojde k chybě
try {
příkaz1();
příkaz2();
příkaz3();
}
catch ( xxxException e ) {
příkazProOšetřeníChyby();
}
Bloky catch
catch (…..
se přeskočí
finally {
ukončovacíPříkazy();
}
dalšíPříkaz();
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
12
Náznak činnosti – ošetřený výjimka
try {
příkaz1(); Při provádění metody příkaz2
dojde k ošetřené chybě
příkaz2();
příkaz3();
Byla vyhozena výjimka
tohoto typu nebo typu
}
některého z potomků
catch ( xxxException e ) {
příkazProOšetřeníChyby();
}
Ostatní bloky catch
catch (…..
se přeskočí
finally {
ukončovacíPříkazy();
}
dalšíPříkaz();
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
13
Náznak činnosti – neošetřená výjimka
Při provádění metody příkaz2
dojde k NEošetřené chybě
try {
příkaz1();
příkaz2();
příkaz3();
}
catch ( xxxException e ) {
příkazProOšetřeníChyby();
}
Ošetření nebylo nalezeno =>
catch (…..
provede se blok finally
a opouští se metoda
finally {
ukončovacíPříkazy();
}
dalšíPříkaz();
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
14
Vyvolání výjimky
public class Xyz implements Comparable
{
public bolean compareTo( Object o )
{
if( !(o instanceOf Xyz) )
throw new ClassCastException (
"\nPokus o porovnání s neporovnatelnou"
+ " instancí " + o );
//Zjištění, kdo je větší
return vysledek;
}
}
► Instanci nemusíme vytvářet až v příkazu throw,
můžeme ji vytvořit kdykoliv před tím a pak mu ji jen předat
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
15
Vaše jistota na trhu IT
Výjimky kontrolované a
nekontrolované
►Hierarchie výjimek
►Pořadí výjimek v blocích catch
►Metody generující výjimky
►Metody třídy Throwable
►Zřetězené výjimky
►Převod kontrolovaných na nekontrolované
Charakteristika
► Výjimky, které jsou potomky třídy RuntimeException
nebo Error označujeme jako nekontrolované (unchecked),
protože překladač nekontroluje, zda je na ně program připraven
► Ostatní výjimky označujeme jako kontrolované (checked),
protože překladač kontroluje dodržení pravidel:
● Každá metoda, která může vyhodit kontrolovanou výjimku,
se musí k této skutečnosti veřejně přihlásit
● Každé použití metody, která může vyhodit kontrolovanou výjimku,
musí být buď uzavřeno v bloku try…catch,
nebo se volající metoda musí přihlásit k tomu,
že může také vyhodit danou kontrolovanou výjimku
► Nekontrolované výjimky ohlašují chyby v programu,
kontrolované výjimky očekávatelné situace,
na jejichž výskyt má být program připraven
a měl by na ně umět reagovat
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
17
Hierarchie výjimek
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
18
Pořadí výjimek v blocích catch
► Třída NumberFormatException
je potomkem třídy RuntimeException
try {
Syntaktická chyba,
......
na druhý blok catch nikdy nedojde
}
catch (RuntimeException e) {
.........
}
Obrácené pořadí bloků catch
catch (NumberFormatException e){
vše vyřeší
........
try {
}
......
}
catch (NumberFormatException e) {
.........
}
catch (RuntimeException e){
........
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
19
Metody generující výjimky
► Java vyžaduje, aby programy, které používají metody
schopné vyvolat kontrolované výjimky,
byly o této schopnosti používaných metod informovány =>
pak vědí, které výjimku musí umět zachytit a ošetřit
► Všechny kontrolované výjimky, které může metoda vyhodit,
musí deklarovat v hlavičce za klíčovým slovem throws
► Deklarace vyhazování nekontrolovaných výjimek není povinná
public void metoda()
throws KontrolovanáVýjimka1,
KontrolovanáVýjimka2
{
// Tělo metody
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
20
Metody třídy Throwable
► String getMessage()
Vrátí zprávu popisující danou výjimku
► String toString()
Vrátí název třídy výjimky následovaný případnou zprávou
► void printStackTrace()
Vytiskne toString() následovaný sadou informací o volající
posloupnosti, která vedla k vzniku výjimky
► Throwable fillInStackTrace()
Připraví nové informace o volací posloupnosti
vedoucí k místu zavolání této metody
► StackTraceElement[] getStackTrace()
Vrátí uchované informace o volací posloupnosti dané výjimky
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
21
Zřetězené výjimky
► V některých situacích je vhodné v rámci ošetření výjimky vyvolat
jinou výjimku, a přitom umožnit zjistit,
která výjimka byla prvotním hybatelem celé akce
► Řada výjimek má mezi svými konstruktory i takové,
které akceptují jako poslední parametr
odkaz na výjimku, jež byla příčinou vyvolání dané výjimky
► Chce-li se program zeptat výjimky na výjimku, která ji způsobila,
použije metodu
public Throwable getCause()
► Ve zprávě o vyvolání výjimky jsou místa, kde byla jedna výjimka
nahrazena jinou, označována textem caused by:
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
22
Ukázka výpisu při zřetězení výjimek
HighLevelException: MidLevelException: LowLevelException
at Junk.a(Junk.java:13)
at Junk.main(Junk.java:4)
Caused by: MidLevelException: LowLevelException
at Junk.c(Junk.java:23)
at Junk.b(Junk.java:17)
at Junk.a(Junk.java:11)
... 1 more
Caused by: LowLevelException
at Junk.e(Junk.java:30)
at Junk.d(Junk.java:27)
at Junk.c(Junk.java:21)
... 3 more
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
23
Převod kontrolovaných na nekontrolované
► Ošetřování kontrolovaných výjimek obtěžuje
► Víme-li, že k dané výjimce nejspíš nedojde
a ošetřujeme-li ji pouze proto, že na tom překladač trvá,
můžeme pro případ, že by k výjimce přece jenom došlo
zaměnit kontrolovanou výjimku za nekontrolovanou
public void prevod( String s ) {
try {
prověř( s );
} catch( Exception ex ) {
throw new RuntimeException( " Neprověřeno! ", ex );
}
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
24
Vaše jistota na trhu IT
Definice vlastních výjimek
►Hierarchie výjimek
►Pořadí výjimek v blocích catch
►Metody generující výjimky
►Metody třídy Throwable
►Vlastní výjimky
►Zásady správného používání výjimek
Definice vlastních výjimek
► Výjimky jsou zcela běžné třídy;
považujeme-li to proto za vhodné, můžeme definovat i vlastní
► Před definicí nové výjimky bychom si měli ujasnit,
bude-li kontrolovaná či nekontrolovaná;
podle toho definujeme jejího předka
► Název výjimek končí dle konvencí slovem Exception
před nímž je naznačena podstata dané výjimky
● IllegalArgumetnException
● NoSuchMethodException
● BadStringOperationException
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
26
Příklad vlastní kontrolované výjimky
public class VelkýPrůšvihException
extends Exception
{
public VelkýPrůšvihException() {};
public VelkýPrůšvihException( String zpráva ) {
super( zpráva );
}
public VelkýPrůšvihException(String zpráva,
Throwable původce ) {
super( zpráva, původce );
}
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
27
Test správného vyhození výjimky
► Na vytvářených programech je třeba otestovat i to,
že v definovaných situacích vyhodí požadovanou výjimku
public void testVyhozeníVýjimky()
{
try {
metodaKteráMáVyhoditVýjimku();
} catch ( VelkýPrůšvihException vpe ) {
return;
}
fail( "Nebyla vyhozena výjimka VelkýPrůšvihException" );
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
28
Zásady správného používání výjimek
1/2
Neignorujte
výjimky
try {
//Nějaký kód
}
catch(Exception e){}
► Výjimky, o nichž víte, že nemohou nastat,
převeďte na nekontrolované pro případ,
že by v budoucích verzích programu nastat mohly
► Při ošetřování výjimek, které nastat mohou,
ale nemají vliv na chod programu,
vložte do těla ošetření alespoň vysvětlující komentář
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
29
Zásady správného používání výjimek
2/2
► Používejte výjimky pouze k ošetření výjimečných stavů
► Kontrolované výjimky používejte u stavů, z nichž se lze zotavit,
jinak použijte výjimky nekontrolované
► Vyhýbejte se zbytečnému používání kontrolovaných výjimek
● Programátory ošetřování kontrolovaných výjimek obtěžuje
a mají pak tendenci je ošetřovat prázdným blokem catch
► Dávejte přednost standardním výjimkám,
vyvolávejte výjimky odpovídající dané abstrakci
● Programátoři by měli z názvu výjimky poznat, co se stalo
● Standardní výjimky mají všeobecně známý význam
► Snažte se o atomičnost selhání; i po vyhození výjimky
by měl být objekt v dobře definovaném stavu
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
30
Zásady správného používání výjimek
3/2
► Doplňujte výjimky zprávami,
výjimka by sama měla poskytnout dostatek informací
a neměla by programátora nutit k podrobnější analýze programu
► Dokumentujte vyvolávané výjimky v dokumentačních
komentářích pomocí značky @throws
► Nedělejte bloky try zbytečně velké,
kód uvnitř těchto bloků se neoptimalizuje
► Umíte-li výjimku v metodě ošetřit, udělejte to
► Detekuje-li se chyba v jedné metodě a má se ošetřit v jiné
(stejné či jiné instance), použijte výjimku.
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
31
Nejčastěji používané výjimky
1/2
► IllegalArgumentException
Byla zadána nepovolená hodnota parametru
● Např. chci nastavit zápornou velikost grafického tvaru
► IllegalStateException
V daném stavu objektu nelze metodu provést
● Např. otevřu soubor, přečtu pár vět, zavřu soubor a chci znovu přečíst větu
► NullPointerException
Byla vyvolána metoda instance, na níž ukazuje prázdný odkaz,
nebo byl předán nepovolený prázdný odkaz v parametru
► ArrayIndexOutOfBoundException
Byly zadány špatné meze pole, buď záporné nebo moc velké
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
32
Nejčastěji používané výjimky
2/2
► ConcurrentModificationException
V průběhu iterace byla změněna struktura kontejneru
● Např. byl do kontejneru přidán prvek
► NumberFormatException
Je požadován špatný převod řetězce na číslo či naopak
● Chci-li např. převést na číslo řetězec, který není číslem
● Častá chyba v metodách String.format či PrintStream.printf
► ClassCastException
Požadované přetypování není možné
► UnsupportedOperationException
Požadovaná operace není podporována
(např. chci přidat prvek do neměnného kontejneru)
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
33
Vaše jistota na trhu IT
Děkuji za pozornost
►Rudolf Pecinovský
http://vyuka.pecinovsky.cz/vse
mail: [email protected]
ICQ: 158 156 600
Slide 26
Vaše jistota na trhu IT
Výjimky
Rudolf Pecinovský
[email protected]
Vaše jistota na trhu IT
Obsah s odkazy
►Výjimky
►Výjimky kontrolované a nekontrolované
►Definice vlastních výjimek
Vaše jistota na trhu IT
Výjimky
►Výjimečné situace v programech
►Ošetření nestandardních situací v Javě
►Zpráva o výjimce
►Klíčová slova
►Činnost
►Vyvolání
Výjimečné situace v programech
► V každém programu je alespoň jedna chyba –
program na ni musí být připraven
► Starší programy
● Program vypsal chybové hlášení a ukončil činnost;
● V některých situacích (válcovací stolice, autopilot, …) nepřijatelné
● Funkce vrátí hodnotu signalizující chybu
● Programátor musí neustále testovat, co funkce vrací
● Knihovna měla pro tyto účely vyhrazenu speciální proměnnou,
do níž se v případě chyby zapsal její kód; nahlédnutím do proměnné
program zjistil kód poslední chyby
● Programátor musí neustále testovat, jaká je v proměnné hodnota
► Některé jazyky (Cobol, PL/1, …) proto přišly s koncepcí
ošetření nestandardních situací
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
4
Ošetření nestandardních situací v Javě
► Výjimečná událost =
problém, který brání dalšímu vykonávání části kódu
► Událost je výjimečná v tom, že na rozdíl od běžných problémů
nemá program k vyřešení situace dost informaci
► Program může při výskytu výjimečné události vyvolat výjimku
► Výjimka (exception)
objekt určený k přenosu informací o nastalém problému
z místa jeho vzniku do místa, kde bude problém řešen
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
5
Postup při vyvolání výjimky
1. Vytvoří se výjimka = objekt typu Throwable
(prakticky vždy instance některého z potomků)
2. Vytvořená výjimka se vyhodí =
přeruší se běh programu v místě, kde výjimka vznikla,
a začne se hledat místo, kde bude daná výjimka ošetřena
3. Ošetření výjimky (handler) by mělo uvést program do stavu,
v němž může jeho vykonávání pokračovat
► Výjimka „probublává“ programem z místa vyhození stále výše
a nenarazí-li cestou nikde na své ošetření,
zachytí ji virtuální stroj, který na standardní chybový výstup
vypíše zprávu o vzniku výjimky
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
6
Systémová zpráva o vzniku výjimky
Zpráva o vzniku výjimky spolu s názvem vlákna,
v němž k výjimce došlo (zde AWT-EventQueue-0)
Popis druhu výjimky (aritmetická výjimka dělení nulou)
Informace o místě, odkud byla volána metoda,
která vyvolala metodu, v níž došlo k vyhození výjimky
Informace o místě, odkud byla volána metoda,
v níž došlo k vyhození výjimky
Úplný název třídy včetně balíčku
Copyright © 2006, Rudolf Pecinovský
Název metody
VŠE – 05
Název souboru se
zdrojovým kódem
Číslo řádku zdrojáku,
kde došlo k výjimce
7
Klíčová slova související s výjimkami
► try (zkus)
Označuje blok kódu, v němž může dojít k výjimce
► throw (hoď)
Příkaz k vyhození výjimky;
musí být následován odkazem na existující instanci
► catch (chyť)
Blok ošetřující výjimku, která je zadána jako parametr
► finally (na konec)
Blok s povinnými závěrečnými akcemi nezávisejícími
na případném vzniku výjimky
► throws (hází)
Uvození seznamu výjimek vyhazovaných danou metodou
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
8
Vyvolání a ošetření výjimky v kódu
try {
//Kód, který může vyvolat výjimky
}
catch( Typ1 id1 ) {
//Ošetření výjimek typu Typ1
}
...
catch( TypN idN ) {
//ošetření výjimek typu TypN
}
finally {
//Kód, který se na závěr VŽDY provede
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
9
Náznak činnosti – řádný průběh
nedojde k vyvolání výjimky
= nedojde k chybě
try {
příkaz1();
příkaz2();
příkaz3();
}
catch ( xxxException e ) {
příkazProOšetřeníChyby();
}
Bloky catch
catch (…..
se přeskočí
finally {
ukončovacíPříkazy();
}
dalšíPříkaz();
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
12
Náznak činnosti – ošetřený výjimka
try {
příkaz1(); Při provádění metody příkaz2
dojde k ošetřené chybě
příkaz2();
příkaz3();
Byla vyhozena výjimka
tohoto typu nebo typu
}
některého z potomků
catch ( xxxException e ) {
příkazProOšetřeníChyby();
}
Ostatní bloky catch
catch (…..
se přeskočí
finally {
ukončovacíPříkazy();
}
dalšíPříkaz();
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
13
Náznak činnosti – neošetřená výjimka
Při provádění metody příkaz2
dojde k NEošetřené chybě
try {
příkaz1();
příkaz2();
příkaz3();
}
catch ( xxxException e ) {
příkazProOšetřeníChyby();
}
Ošetření nebylo nalezeno =>
catch (…..
provede se blok finally
a opouští se metoda
finally {
ukončovacíPříkazy();
}
dalšíPříkaz();
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
14
Vyvolání výjimky
public class Xyz implements Comparable
{
public bolean compareTo( Object o )
{
if( !(o instanceOf Xyz) )
throw new ClassCastException (
"\nPokus o porovnání s neporovnatelnou"
+ " instancí " + o );
//Zjištění, kdo je větší
return vysledek;
}
}
► Instanci nemusíme vytvářet až v příkazu throw,
můžeme ji vytvořit kdykoliv před tím a pak mu ji jen předat
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
15
Vaše jistota na trhu IT
Výjimky kontrolované a
nekontrolované
►Hierarchie výjimek
►Pořadí výjimek v blocích catch
►Metody generující výjimky
►Metody třídy Throwable
►Zřetězené výjimky
►Převod kontrolovaných na nekontrolované
Charakteristika
► Výjimky, které jsou potomky třídy RuntimeException
nebo Error označujeme jako nekontrolované (unchecked),
protože překladač nekontroluje, zda je na ně program připraven
► Ostatní výjimky označujeme jako kontrolované (checked),
protože překladač kontroluje dodržení pravidel:
● Každá metoda, která může vyhodit kontrolovanou výjimku,
se musí k této skutečnosti veřejně přihlásit
● Každé použití metody, která může vyhodit kontrolovanou výjimku,
musí být buď uzavřeno v bloku try…catch,
nebo se volající metoda musí přihlásit k tomu,
že může také vyhodit danou kontrolovanou výjimku
► Nekontrolované výjimky ohlašují chyby v programu,
kontrolované výjimky očekávatelné situace,
na jejichž výskyt má být program připraven
a měl by na ně umět reagovat
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
17
Hierarchie výjimek
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
18
Pořadí výjimek v blocích catch
► Třída NumberFormatException
je potomkem třídy RuntimeException
try {
Syntaktická chyba,
......
na druhý blok catch nikdy nedojde
}
catch (RuntimeException e) {
.........
}
Obrácené pořadí bloků catch
catch (NumberFormatException e){
vše vyřeší
........
try {
}
......
}
catch (NumberFormatException e) {
.........
}
catch (RuntimeException e){
........
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
19
Metody generující výjimky
► Java vyžaduje, aby programy, které používají metody
schopné vyvolat kontrolované výjimky,
byly o této schopnosti používaných metod informovány =>
pak vědí, které výjimku musí umět zachytit a ošetřit
► Všechny kontrolované výjimky, které může metoda vyhodit,
musí deklarovat v hlavičce za klíčovým slovem throws
► Deklarace vyhazování nekontrolovaných výjimek není povinná
public void metoda()
throws KontrolovanáVýjimka1,
KontrolovanáVýjimka2
{
// Tělo metody
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
20
Metody třídy Throwable
► String getMessage()
Vrátí zprávu popisující danou výjimku
► String toString()
Vrátí název třídy výjimky následovaný případnou zprávou
► void printStackTrace()
Vytiskne toString() následovaný sadou informací o volající
posloupnosti, která vedla k vzniku výjimky
► Throwable fillInStackTrace()
Připraví nové informace o volací posloupnosti
vedoucí k místu zavolání této metody
► StackTraceElement[] getStackTrace()
Vrátí uchované informace o volací posloupnosti dané výjimky
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
21
Zřetězené výjimky
► V některých situacích je vhodné v rámci ošetření výjimky vyvolat
jinou výjimku, a přitom umožnit zjistit,
která výjimka byla prvotním hybatelem celé akce
► Řada výjimek má mezi svými konstruktory i takové,
které akceptují jako poslední parametr
odkaz na výjimku, jež byla příčinou vyvolání dané výjimky
► Chce-li se program zeptat výjimky na výjimku, která ji způsobila,
použije metodu
public Throwable getCause()
► Ve zprávě o vyvolání výjimky jsou místa, kde byla jedna výjimka
nahrazena jinou, označována textem caused by:
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
22
Ukázka výpisu při zřetězení výjimek
HighLevelException: MidLevelException: LowLevelException
at Junk.a(Junk.java:13)
at Junk.main(Junk.java:4)
Caused by: MidLevelException: LowLevelException
at Junk.c(Junk.java:23)
at Junk.b(Junk.java:17)
at Junk.a(Junk.java:11)
... 1 more
Caused by: LowLevelException
at Junk.e(Junk.java:30)
at Junk.d(Junk.java:27)
at Junk.c(Junk.java:21)
... 3 more
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
23
Převod kontrolovaných na nekontrolované
► Ošetřování kontrolovaných výjimek obtěžuje
► Víme-li, že k dané výjimce nejspíš nedojde
a ošetřujeme-li ji pouze proto, že na tom překladač trvá,
můžeme pro případ, že by k výjimce přece jenom došlo
zaměnit kontrolovanou výjimku za nekontrolovanou
public void prevod( String s ) {
try {
prověř( s );
} catch( Exception ex ) {
throw new RuntimeException( " Neprověřeno! ", ex );
}
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
24
Vaše jistota na trhu IT
Definice vlastních výjimek
►Hierarchie výjimek
►Pořadí výjimek v blocích catch
►Metody generující výjimky
►Metody třídy Throwable
►Vlastní výjimky
►Zásady správného používání výjimek
Definice vlastních výjimek
► Výjimky jsou zcela běžné třídy;
považujeme-li to proto za vhodné, můžeme definovat i vlastní
► Před definicí nové výjimky bychom si měli ujasnit,
bude-li kontrolovaná či nekontrolovaná;
podle toho definujeme jejího předka
► Název výjimek končí dle konvencí slovem Exception
před nímž je naznačena podstata dané výjimky
● IllegalArgumetnException
● NoSuchMethodException
● BadStringOperationException
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
26
Příklad vlastní kontrolované výjimky
public class VelkýPrůšvihException
extends Exception
{
public VelkýPrůšvihException() {};
public VelkýPrůšvihException( String zpráva ) {
super( zpráva );
}
public VelkýPrůšvihException(String zpráva,
Throwable původce ) {
super( zpráva, původce );
}
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
27
Test správného vyhození výjimky
► Na vytvářených programech je třeba otestovat i to,
že v definovaných situacích vyhodí požadovanou výjimku
public void testVyhozeníVýjimky()
{
try {
metodaKteráMáVyhoditVýjimku();
} catch ( VelkýPrůšvihException vpe ) {
return;
}
fail( "Nebyla vyhozena výjimka VelkýPrůšvihException" );
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
28
Zásady správného používání výjimek
1/2
Neignorujte
výjimky
try {
//Nějaký kód
}
catch(Exception e){}
► Výjimky, o nichž víte, že nemohou nastat,
převeďte na nekontrolované pro případ,
že by v budoucích verzích programu nastat mohly
► Při ošetřování výjimek, které nastat mohou,
ale nemají vliv na chod programu,
vložte do těla ošetření alespoň vysvětlující komentář
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
29
Zásady správného používání výjimek
2/2
► Používejte výjimky pouze k ošetření výjimečných stavů
► Kontrolované výjimky používejte u stavů, z nichž se lze zotavit,
jinak použijte výjimky nekontrolované
► Vyhýbejte se zbytečnému používání kontrolovaných výjimek
● Programátory ošetřování kontrolovaných výjimek obtěžuje
a mají pak tendenci je ošetřovat prázdným blokem catch
► Dávejte přednost standardním výjimkám,
vyvolávejte výjimky odpovídající dané abstrakci
● Programátoři by měli z názvu výjimky poznat, co se stalo
● Standardní výjimky mají všeobecně známý význam
► Snažte se o atomičnost selhání; i po vyhození výjimky
by měl být objekt v dobře definovaném stavu
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
30
Zásady správného používání výjimek
3/2
► Doplňujte výjimky zprávami,
výjimka by sama měla poskytnout dostatek informací
a neměla by programátora nutit k podrobnější analýze programu
► Dokumentujte vyvolávané výjimky v dokumentačních
komentářích pomocí značky @throws
► Nedělejte bloky try zbytečně velké,
kód uvnitř těchto bloků se neoptimalizuje
► Umíte-li výjimku v metodě ošetřit, udělejte to
► Detekuje-li se chyba v jedné metodě a má se ošetřit v jiné
(stejné či jiné instance), použijte výjimku.
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
31
Nejčastěji používané výjimky
1/2
► IllegalArgumentException
Byla zadána nepovolená hodnota parametru
● Např. chci nastavit zápornou velikost grafického tvaru
► IllegalStateException
V daném stavu objektu nelze metodu provést
● Např. otevřu soubor, přečtu pár vět, zavřu soubor a chci znovu přečíst větu
► NullPointerException
Byla vyvolána metoda instance, na níž ukazuje prázdný odkaz,
nebo byl předán nepovolený prázdný odkaz v parametru
► ArrayIndexOutOfBoundException
Byly zadány špatné meze pole, buď záporné nebo moc velké
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
32
Nejčastěji používané výjimky
2/2
► ConcurrentModificationException
V průběhu iterace byla změněna struktura kontejneru
● Např. byl do kontejneru přidán prvek
► NumberFormatException
Je požadován špatný převod řetězce na číslo či naopak
● Chci-li např. převést na číslo řetězec, který není číslem
● Častá chyba v metodách String.format či PrintStream.printf
► ClassCastException
Požadované přetypování není možné
► UnsupportedOperationException
Požadovaná operace není podporována
(např. chci přidat prvek do neměnného kontejneru)
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
33
Vaše jistota na trhu IT
Děkuji za pozornost
►Rudolf Pecinovský
http://vyuka.pecinovsky.cz/vse
mail: [email protected]
ICQ: 158 156 600
Slide 27
Vaše jistota na trhu IT
Výjimky
Rudolf Pecinovský
[email protected]
Vaše jistota na trhu IT
Obsah s odkazy
►Výjimky
►Výjimky kontrolované a nekontrolované
►Definice vlastních výjimek
Vaše jistota na trhu IT
Výjimky
►Výjimečné situace v programech
►Ošetření nestandardních situací v Javě
►Zpráva o výjimce
►Klíčová slova
►Činnost
►Vyvolání
Výjimečné situace v programech
► V každém programu je alespoň jedna chyba –
program na ni musí být připraven
► Starší programy
● Program vypsal chybové hlášení a ukončil činnost;
● V některých situacích (válcovací stolice, autopilot, …) nepřijatelné
● Funkce vrátí hodnotu signalizující chybu
● Programátor musí neustále testovat, co funkce vrací
● Knihovna měla pro tyto účely vyhrazenu speciální proměnnou,
do níž se v případě chyby zapsal její kód; nahlédnutím do proměnné
program zjistil kód poslední chyby
● Programátor musí neustále testovat, jaká je v proměnné hodnota
► Některé jazyky (Cobol, PL/1, …) proto přišly s koncepcí
ošetření nestandardních situací
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
4
Ošetření nestandardních situací v Javě
► Výjimečná událost =
problém, který brání dalšímu vykonávání části kódu
► Událost je výjimečná v tom, že na rozdíl od běžných problémů
nemá program k vyřešení situace dost informaci
► Program může při výskytu výjimečné události vyvolat výjimku
► Výjimka (exception)
objekt určený k přenosu informací o nastalém problému
z místa jeho vzniku do místa, kde bude problém řešen
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
5
Postup při vyvolání výjimky
1. Vytvoří se výjimka = objekt typu Throwable
(prakticky vždy instance některého z potomků)
2. Vytvořená výjimka se vyhodí =
přeruší se běh programu v místě, kde výjimka vznikla,
a začne se hledat místo, kde bude daná výjimka ošetřena
3. Ošetření výjimky (handler) by mělo uvést program do stavu,
v němž může jeho vykonávání pokračovat
► Výjimka „probublává“ programem z místa vyhození stále výše
a nenarazí-li cestou nikde na své ošetření,
zachytí ji virtuální stroj, který na standardní chybový výstup
vypíše zprávu o vzniku výjimky
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
6
Systémová zpráva o vzniku výjimky
Zpráva o vzniku výjimky spolu s názvem vlákna,
v němž k výjimce došlo (zde AWT-EventQueue-0)
Popis druhu výjimky (aritmetická výjimka dělení nulou)
Informace o místě, odkud byla volána metoda,
která vyvolala metodu, v níž došlo k vyhození výjimky
Informace o místě, odkud byla volána metoda,
v níž došlo k vyhození výjimky
Úplný název třídy včetně balíčku
Copyright © 2006, Rudolf Pecinovský
Název metody
VŠE – 05
Název souboru se
zdrojovým kódem
Číslo řádku zdrojáku,
kde došlo k výjimce
7
Klíčová slova související s výjimkami
► try (zkus)
Označuje blok kódu, v němž může dojít k výjimce
► throw (hoď)
Příkaz k vyhození výjimky;
musí být následován odkazem na existující instanci
► catch (chyť)
Blok ošetřující výjimku, která je zadána jako parametr
► finally (na konec)
Blok s povinnými závěrečnými akcemi nezávisejícími
na případném vzniku výjimky
► throws (hází)
Uvození seznamu výjimek vyhazovaných danou metodou
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
8
Vyvolání a ošetření výjimky v kódu
try {
//Kód, který může vyvolat výjimky
}
catch( Typ1 id1 ) {
//Ošetření výjimek typu Typ1
}
...
catch( TypN idN ) {
//ošetření výjimek typu TypN
}
finally {
//Kód, který se na závěr VŽDY provede
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
9
Náznak činnosti – řádný průběh
nedojde k vyvolání výjimky
= nedojde k chybě
try {
příkaz1();
příkaz2();
příkaz3();
}
catch ( xxxException e ) {
příkazProOšetřeníChyby();
}
Bloky catch
catch (…..
se přeskočí
finally {
ukončovacíPříkazy();
}
dalšíPříkaz();
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
12
Náznak činnosti – ošetřený výjimka
try {
příkaz1(); Při provádění metody příkaz2
dojde k ošetřené chybě
příkaz2();
příkaz3();
Byla vyhozena výjimka
tohoto typu nebo typu
}
některého z potomků
catch ( xxxException e ) {
příkazProOšetřeníChyby();
}
Ostatní bloky catch
catch (…..
se přeskočí
finally {
ukončovacíPříkazy();
}
dalšíPříkaz();
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
13
Náznak činnosti – neošetřená výjimka
Při provádění metody příkaz2
dojde k NEošetřené chybě
try {
příkaz1();
příkaz2();
příkaz3();
}
catch ( xxxException e ) {
příkazProOšetřeníChyby();
}
Ošetření nebylo nalezeno =>
catch (…..
provede se blok finally
a opouští se metoda
finally {
ukončovacíPříkazy();
}
dalšíPříkaz();
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
14
Vyvolání výjimky
public class Xyz implements Comparable
{
public bolean compareTo( Object o )
{
if( !(o instanceOf Xyz) )
throw new ClassCastException (
"\nPokus o porovnání s neporovnatelnou"
+ " instancí " + o );
//Zjištění, kdo je větší
return vysledek;
}
}
► Instanci nemusíme vytvářet až v příkazu throw,
můžeme ji vytvořit kdykoliv před tím a pak mu ji jen předat
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
15
Vaše jistota na trhu IT
Výjimky kontrolované a
nekontrolované
►Hierarchie výjimek
►Pořadí výjimek v blocích catch
►Metody generující výjimky
►Metody třídy Throwable
►Zřetězené výjimky
►Převod kontrolovaných na nekontrolované
Charakteristika
► Výjimky, které jsou potomky třídy RuntimeException
nebo Error označujeme jako nekontrolované (unchecked),
protože překladač nekontroluje, zda je na ně program připraven
► Ostatní výjimky označujeme jako kontrolované (checked),
protože překladač kontroluje dodržení pravidel:
● Každá metoda, která může vyhodit kontrolovanou výjimku,
se musí k této skutečnosti veřejně přihlásit
● Každé použití metody, která může vyhodit kontrolovanou výjimku,
musí být buď uzavřeno v bloku try…catch,
nebo se volající metoda musí přihlásit k tomu,
že může také vyhodit danou kontrolovanou výjimku
► Nekontrolované výjimky ohlašují chyby v programu,
kontrolované výjimky očekávatelné situace,
na jejichž výskyt má být program připraven
a měl by na ně umět reagovat
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
17
Hierarchie výjimek
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
18
Pořadí výjimek v blocích catch
► Třída NumberFormatException
je potomkem třídy RuntimeException
try {
Syntaktická chyba,
......
na druhý blok catch nikdy nedojde
}
catch (RuntimeException e) {
.........
}
Obrácené pořadí bloků catch
catch (NumberFormatException e){
vše vyřeší
........
try {
}
......
}
catch (NumberFormatException e) {
.........
}
catch (RuntimeException e){
........
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
19
Metody generující výjimky
► Java vyžaduje, aby programy, které používají metody
schopné vyvolat kontrolované výjimky,
byly o této schopnosti používaných metod informovány =>
pak vědí, které výjimku musí umět zachytit a ošetřit
► Všechny kontrolované výjimky, které může metoda vyhodit,
musí deklarovat v hlavičce za klíčovým slovem throws
► Deklarace vyhazování nekontrolovaných výjimek není povinná
public void metoda()
throws KontrolovanáVýjimka1,
KontrolovanáVýjimka2
{
// Tělo metody
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
20
Metody třídy Throwable
► String getMessage()
Vrátí zprávu popisující danou výjimku
► String toString()
Vrátí název třídy výjimky následovaný případnou zprávou
► void printStackTrace()
Vytiskne toString() následovaný sadou informací o volající
posloupnosti, která vedla k vzniku výjimky
► Throwable fillInStackTrace()
Připraví nové informace o volací posloupnosti
vedoucí k místu zavolání této metody
► StackTraceElement[] getStackTrace()
Vrátí uchované informace o volací posloupnosti dané výjimky
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
21
Zřetězené výjimky
► V některých situacích je vhodné v rámci ošetření výjimky vyvolat
jinou výjimku, a přitom umožnit zjistit,
která výjimka byla prvotním hybatelem celé akce
► Řada výjimek má mezi svými konstruktory i takové,
které akceptují jako poslední parametr
odkaz na výjimku, jež byla příčinou vyvolání dané výjimky
► Chce-li se program zeptat výjimky na výjimku, která ji způsobila,
použije metodu
public Throwable getCause()
► Ve zprávě o vyvolání výjimky jsou místa, kde byla jedna výjimka
nahrazena jinou, označována textem caused by:
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
22
Ukázka výpisu při zřetězení výjimek
HighLevelException: MidLevelException: LowLevelException
at Junk.a(Junk.java:13)
at Junk.main(Junk.java:4)
Caused by: MidLevelException: LowLevelException
at Junk.c(Junk.java:23)
at Junk.b(Junk.java:17)
at Junk.a(Junk.java:11)
... 1 more
Caused by: LowLevelException
at Junk.e(Junk.java:30)
at Junk.d(Junk.java:27)
at Junk.c(Junk.java:21)
... 3 more
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
23
Převod kontrolovaných na nekontrolované
► Ošetřování kontrolovaných výjimek obtěžuje
► Víme-li, že k dané výjimce nejspíš nedojde
a ošetřujeme-li ji pouze proto, že na tom překladač trvá,
můžeme pro případ, že by k výjimce přece jenom došlo
zaměnit kontrolovanou výjimku za nekontrolovanou
public void prevod( String s ) {
try {
prověř( s );
} catch( Exception ex ) {
throw new RuntimeException( " Neprověřeno! ", ex );
}
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
24
Vaše jistota na trhu IT
Definice vlastních výjimek
►Hierarchie výjimek
►Pořadí výjimek v blocích catch
►Metody generující výjimky
►Metody třídy Throwable
►Vlastní výjimky
►Zásady správného používání výjimek
Definice vlastních výjimek
► Výjimky jsou zcela běžné třídy;
považujeme-li to proto za vhodné, můžeme definovat i vlastní
► Před definicí nové výjimky bychom si měli ujasnit,
bude-li kontrolovaná či nekontrolovaná;
podle toho definujeme jejího předka
► Název výjimek končí dle konvencí slovem Exception
před nímž je naznačena podstata dané výjimky
● IllegalArgumetnException
● NoSuchMethodException
● BadStringOperationException
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
26
Příklad vlastní kontrolované výjimky
public class VelkýPrůšvihException
extends Exception
{
public VelkýPrůšvihException() {};
public VelkýPrůšvihException( String zpráva ) {
super( zpráva );
}
public VelkýPrůšvihException(String zpráva,
Throwable původce ) {
super( zpráva, původce );
}
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
27
Test správného vyhození výjimky
► Na vytvářených programech je třeba otestovat i to,
že v definovaných situacích vyhodí požadovanou výjimku
public void testVyhozeníVýjimky()
{
try {
metodaKteráMáVyhoditVýjimku();
} catch ( VelkýPrůšvihException vpe ) {
return;
}
fail( "Nebyla vyhozena výjimka VelkýPrůšvihException" );
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
28
Zásady správného používání výjimek
1/2
Neignorujte
výjimky
try {
//Nějaký kód
}
catch(Exception e){}
► Výjimky, o nichž víte, že nemohou nastat,
převeďte na nekontrolované pro případ,
že by v budoucích verzích programu nastat mohly
► Při ošetřování výjimek, které nastat mohou,
ale nemají vliv na chod programu,
vložte do těla ošetření alespoň vysvětlující komentář
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
29
Zásady správného používání výjimek
2/2
► Používejte výjimky pouze k ošetření výjimečných stavů
► Kontrolované výjimky používejte u stavů, z nichž se lze zotavit,
jinak použijte výjimky nekontrolované
► Vyhýbejte se zbytečnému používání kontrolovaných výjimek
● Programátory ošetřování kontrolovaných výjimek obtěžuje
a mají pak tendenci je ošetřovat prázdným blokem catch
► Dávejte přednost standardním výjimkám,
vyvolávejte výjimky odpovídající dané abstrakci
● Programátoři by měli z názvu výjimky poznat, co se stalo
● Standardní výjimky mají všeobecně známý význam
► Snažte se o atomičnost selhání; i po vyhození výjimky
by měl být objekt v dobře definovaném stavu
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
30
Zásady správného používání výjimek
3/2
► Doplňujte výjimky zprávami,
výjimka by sama měla poskytnout dostatek informací
a neměla by programátora nutit k podrobnější analýze programu
► Dokumentujte vyvolávané výjimky v dokumentačních
komentářích pomocí značky @throws
► Nedělejte bloky try zbytečně velké,
kód uvnitř těchto bloků se neoptimalizuje
► Umíte-li výjimku v metodě ošetřit, udělejte to
► Detekuje-li se chyba v jedné metodě a má se ošetřit v jiné
(stejné či jiné instance), použijte výjimku.
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
31
Nejčastěji používané výjimky
1/2
► IllegalArgumentException
Byla zadána nepovolená hodnota parametru
● Např. chci nastavit zápornou velikost grafického tvaru
► IllegalStateException
V daném stavu objektu nelze metodu provést
● Např. otevřu soubor, přečtu pár vět, zavřu soubor a chci znovu přečíst větu
► NullPointerException
Byla vyvolána metoda instance, na níž ukazuje prázdný odkaz,
nebo byl předán nepovolený prázdný odkaz v parametru
► ArrayIndexOutOfBoundException
Byly zadány špatné meze pole, buď záporné nebo moc velké
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
32
Nejčastěji používané výjimky
2/2
► ConcurrentModificationException
V průběhu iterace byla změněna struktura kontejneru
● Např. byl do kontejneru přidán prvek
► NumberFormatException
Je požadován špatný převod řetězce na číslo či naopak
● Chci-li např. převést na číslo řetězec, který není číslem
● Častá chyba v metodách String.format či PrintStream.printf
► ClassCastException
Požadované přetypování není možné
► UnsupportedOperationException
Požadovaná operace není podporována
(např. chci přidat prvek do neměnného kontejneru)
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
33
Vaše jistota na trhu IT
Děkuji za pozornost
►Rudolf Pecinovský
http://vyuka.pecinovsky.cz/vse
mail: [email protected]
ICQ: 158 156 600
Slide 28
Vaše jistota na trhu IT
Výjimky
Rudolf Pecinovský
[email protected]
Vaše jistota na trhu IT
Obsah s odkazy
►Výjimky
►Výjimky kontrolované a nekontrolované
►Definice vlastních výjimek
Vaše jistota na trhu IT
Výjimky
►Výjimečné situace v programech
►Ošetření nestandardních situací v Javě
►Zpráva o výjimce
►Klíčová slova
►Činnost
►Vyvolání
Výjimečné situace v programech
► V každém programu je alespoň jedna chyba –
program na ni musí být připraven
► Starší programy
● Program vypsal chybové hlášení a ukončil činnost;
● V některých situacích (válcovací stolice, autopilot, …) nepřijatelné
● Funkce vrátí hodnotu signalizující chybu
● Programátor musí neustále testovat, co funkce vrací
● Knihovna měla pro tyto účely vyhrazenu speciální proměnnou,
do níž se v případě chyby zapsal její kód; nahlédnutím do proměnné
program zjistil kód poslední chyby
● Programátor musí neustále testovat, jaká je v proměnné hodnota
► Některé jazyky (Cobol, PL/1, …) proto přišly s koncepcí
ošetření nestandardních situací
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
4
Ošetření nestandardních situací v Javě
► Výjimečná událost =
problém, který brání dalšímu vykonávání části kódu
► Událost je výjimečná v tom, že na rozdíl od běžných problémů
nemá program k vyřešení situace dost informaci
► Program může při výskytu výjimečné události vyvolat výjimku
► Výjimka (exception)
objekt určený k přenosu informací o nastalém problému
z místa jeho vzniku do místa, kde bude problém řešen
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
5
Postup při vyvolání výjimky
1. Vytvoří se výjimka = objekt typu Throwable
(prakticky vždy instance některého z potomků)
2. Vytvořená výjimka se vyhodí =
přeruší se běh programu v místě, kde výjimka vznikla,
a začne se hledat místo, kde bude daná výjimka ošetřena
3. Ošetření výjimky (handler) by mělo uvést program do stavu,
v němž může jeho vykonávání pokračovat
► Výjimka „probublává“ programem z místa vyhození stále výše
a nenarazí-li cestou nikde na své ošetření,
zachytí ji virtuální stroj, který na standardní chybový výstup
vypíše zprávu o vzniku výjimky
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
6
Systémová zpráva o vzniku výjimky
Zpráva o vzniku výjimky spolu s názvem vlákna,
v němž k výjimce došlo (zde AWT-EventQueue-0)
Popis druhu výjimky (aritmetická výjimka dělení nulou)
Informace o místě, odkud byla volána metoda,
která vyvolala metodu, v níž došlo k vyhození výjimky
Informace o místě, odkud byla volána metoda,
v níž došlo k vyhození výjimky
Úplný název třídy včetně balíčku
Copyright © 2006, Rudolf Pecinovský
Název metody
VŠE – 05
Název souboru se
zdrojovým kódem
Číslo řádku zdrojáku,
kde došlo k výjimce
7
Klíčová slova související s výjimkami
► try (zkus)
Označuje blok kódu, v němž může dojít k výjimce
► throw (hoď)
Příkaz k vyhození výjimky;
musí být následován odkazem na existující instanci
► catch (chyť)
Blok ošetřující výjimku, která je zadána jako parametr
► finally (na konec)
Blok s povinnými závěrečnými akcemi nezávisejícími
na případném vzniku výjimky
► throws (hází)
Uvození seznamu výjimek vyhazovaných danou metodou
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
8
Vyvolání a ošetření výjimky v kódu
try {
//Kód, který může vyvolat výjimky
}
catch( Typ1 id1 ) {
//Ošetření výjimek typu Typ1
}
...
catch( TypN idN ) {
//ošetření výjimek typu TypN
}
finally {
//Kód, který se na závěr VŽDY provede
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
9
Náznak činnosti – řádný průběh
nedojde k vyvolání výjimky
= nedojde k chybě
try {
příkaz1();
příkaz2();
příkaz3();
}
catch ( xxxException e ) {
příkazProOšetřeníChyby();
}
Bloky catch
catch (…..
se přeskočí
finally {
ukončovacíPříkazy();
}
dalšíPříkaz();
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
12
Náznak činnosti – ošetřený výjimka
try {
příkaz1(); Při provádění metody příkaz2
dojde k ošetřené chybě
příkaz2();
příkaz3();
Byla vyhozena výjimka
tohoto typu nebo typu
}
některého z potomků
catch ( xxxException e ) {
příkazProOšetřeníChyby();
}
Ostatní bloky catch
catch (…..
se přeskočí
finally {
ukončovacíPříkazy();
}
dalšíPříkaz();
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
13
Náznak činnosti – neošetřená výjimka
Při provádění metody příkaz2
dojde k NEošetřené chybě
try {
příkaz1();
příkaz2();
příkaz3();
}
catch ( xxxException e ) {
příkazProOšetřeníChyby();
}
Ošetření nebylo nalezeno =>
catch (…..
provede se blok finally
a opouští se metoda
finally {
ukončovacíPříkazy();
}
dalšíPříkaz();
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
14
Vyvolání výjimky
public class Xyz implements Comparable
{
public bolean compareTo( Object o )
{
if( !(o instanceOf Xyz) )
throw new ClassCastException (
"\nPokus o porovnání s neporovnatelnou"
+ " instancí " + o );
//Zjištění, kdo je větší
return vysledek;
}
}
► Instanci nemusíme vytvářet až v příkazu throw,
můžeme ji vytvořit kdykoliv před tím a pak mu ji jen předat
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
15
Vaše jistota na trhu IT
Výjimky kontrolované a
nekontrolované
►Hierarchie výjimek
►Pořadí výjimek v blocích catch
►Metody generující výjimky
►Metody třídy Throwable
►Zřetězené výjimky
►Převod kontrolovaných na nekontrolované
Charakteristika
► Výjimky, které jsou potomky třídy RuntimeException
nebo Error označujeme jako nekontrolované (unchecked),
protože překladač nekontroluje, zda je na ně program připraven
► Ostatní výjimky označujeme jako kontrolované (checked),
protože překladač kontroluje dodržení pravidel:
● Každá metoda, která může vyhodit kontrolovanou výjimku,
se musí k této skutečnosti veřejně přihlásit
● Každé použití metody, která může vyhodit kontrolovanou výjimku,
musí být buď uzavřeno v bloku try…catch,
nebo se volající metoda musí přihlásit k tomu,
že může také vyhodit danou kontrolovanou výjimku
► Nekontrolované výjimky ohlašují chyby v programu,
kontrolované výjimky očekávatelné situace,
na jejichž výskyt má být program připraven
a měl by na ně umět reagovat
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
17
Hierarchie výjimek
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
18
Pořadí výjimek v blocích catch
► Třída NumberFormatException
je potomkem třídy RuntimeException
try {
Syntaktická chyba,
......
na druhý blok catch nikdy nedojde
}
catch (RuntimeException e) {
.........
}
Obrácené pořadí bloků catch
catch (NumberFormatException e){
vše vyřeší
........
try {
}
......
}
catch (NumberFormatException e) {
.........
}
catch (RuntimeException e){
........
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
19
Metody generující výjimky
► Java vyžaduje, aby programy, které používají metody
schopné vyvolat kontrolované výjimky,
byly o této schopnosti používaných metod informovány =>
pak vědí, které výjimku musí umět zachytit a ošetřit
► Všechny kontrolované výjimky, které může metoda vyhodit,
musí deklarovat v hlavičce za klíčovým slovem throws
► Deklarace vyhazování nekontrolovaných výjimek není povinná
public void metoda()
throws KontrolovanáVýjimka1,
KontrolovanáVýjimka2
{
// Tělo metody
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
20
Metody třídy Throwable
► String getMessage()
Vrátí zprávu popisující danou výjimku
► String toString()
Vrátí název třídy výjimky následovaný případnou zprávou
► void printStackTrace()
Vytiskne toString() následovaný sadou informací o volající
posloupnosti, která vedla k vzniku výjimky
► Throwable fillInStackTrace()
Připraví nové informace o volací posloupnosti
vedoucí k místu zavolání této metody
► StackTraceElement[] getStackTrace()
Vrátí uchované informace o volací posloupnosti dané výjimky
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
21
Zřetězené výjimky
► V některých situacích je vhodné v rámci ošetření výjimky vyvolat
jinou výjimku, a přitom umožnit zjistit,
která výjimka byla prvotním hybatelem celé akce
► Řada výjimek má mezi svými konstruktory i takové,
které akceptují jako poslední parametr
odkaz na výjimku, jež byla příčinou vyvolání dané výjimky
► Chce-li se program zeptat výjimky na výjimku, která ji způsobila,
použije metodu
public Throwable getCause()
► Ve zprávě o vyvolání výjimky jsou místa, kde byla jedna výjimka
nahrazena jinou, označována textem caused by:
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
22
Ukázka výpisu při zřetězení výjimek
HighLevelException: MidLevelException: LowLevelException
at Junk.a(Junk.java:13)
at Junk.main(Junk.java:4)
Caused by: MidLevelException: LowLevelException
at Junk.c(Junk.java:23)
at Junk.b(Junk.java:17)
at Junk.a(Junk.java:11)
... 1 more
Caused by: LowLevelException
at Junk.e(Junk.java:30)
at Junk.d(Junk.java:27)
at Junk.c(Junk.java:21)
... 3 more
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
23
Převod kontrolovaných na nekontrolované
► Ošetřování kontrolovaných výjimek obtěžuje
► Víme-li, že k dané výjimce nejspíš nedojde
a ošetřujeme-li ji pouze proto, že na tom překladač trvá,
můžeme pro případ, že by k výjimce přece jenom došlo
zaměnit kontrolovanou výjimku za nekontrolovanou
public void prevod( String s ) {
try {
prověř( s );
} catch( Exception ex ) {
throw new RuntimeException( " Neprověřeno! ", ex );
}
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
24
Vaše jistota na trhu IT
Definice vlastních výjimek
►Hierarchie výjimek
►Pořadí výjimek v blocích catch
►Metody generující výjimky
►Metody třídy Throwable
►Vlastní výjimky
►Zásady správného používání výjimek
Definice vlastních výjimek
► Výjimky jsou zcela běžné třídy;
považujeme-li to proto za vhodné, můžeme definovat i vlastní
► Před definicí nové výjimky bychom si měli ujasnit,
bude-li kontrolovaná či nekontrolovaná;
podle toho definujeme jejího předka
► Název výjimek končí dle konvencí slovem Exception
před nímž je naznačena podstata dané výjimky
● IllegalArgumetnException
● NoSuchMethodException
● BadStringOperationException
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
26
Příklad vlastní kontrolované výjimky
public class VelkýPrůšvihException
extends Exception
{
public VelkýPrůšvihException() {};
public VelkýPrůšvihException( String zpráva ) {
super( zpráva );
}
public VelkýPrůšvihException(String zpráva,
Throwable původce ) {
super( zpráva, původce );
}
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
27
Test správného vyhození výjimky
► Na vytvářených programech je třeba otestovat i to,
že v definovaných situacích vyhodí požadovanou výjimku
public void testVyhozeníVýjimky()
{
try {
metodaKteráMáVyhoditVýjimku();
} catch ( VelkýPrůšvihException vpe ) {
return;
}
fail( "Nebyla vyhozena výjimka VelkýPrůšvihException" );
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
28
Zásady správného používání výjimek
1/2
Neignorujte
výjimky
try {
//Nějaký kód
}
catch(Exception e){}
► Výjimky, o nichž víte, že nemohou nastat,
převeďte na nekontrolované pro případ,
že by v budoucích verzích programu nastat mohly
► Při ošetřování výjimek, které nastat mohou,
ale nemají vliv na chod programu,
vložte do těla ošetření alespoň vysvětlující komentář
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
29
Zásady správného používání výjimek
2/2
► Používejte výjimky pouze k ošetření výjimečných stavů
► Kontrolované výjimky používejte u stavů, z nichž se lze zotavit,
jinak použijte výjimky nekontrolované
► Vyhýbejte se zbytečnému používání kontrolovaných výjimek
● Programátory ošetřování kontrolovaných výjimek obtěžuje
a mají pak tendenci je ošetřovat prázdným blokem catch
► Dávejte přednost standardním výjimkám,
vyvolávejte výjimky odpovídající dané abstrakci
● Programátoři by měli z názvu výjimky poznat, co se stalo
● Standardní výjimky mají všeobecně známý význam
► Snažte se o atomičnost selhání; i po vyhození výjimky
by měl být objekt v dobře definovaném stavu
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
30
Zásady správného používání výjimek
3/2
► Doplňujte výjimky zprávami,
výjimka by sama měla poskytnout dostatek informací
a neměla by programátora nutit k podrobnější analýze programu
► Dokumentujte vyvolávané výjimky v dokumentačních
komentářích pomocí značky @throws
► Nedělejte bloky try zbytečně velké,
kód uvnitř těchto bloků se neoptimalizuje
► Umíte-li výjimku v metodě ošetřit, udělejte to
► Detekuje-li se chyba v jedné metodě a má se ošetřit v jiné
(stejné či jiné instance), použijte výjimku.
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
31
Nejčastěji používané výjimky
1/2
► IllegalArgumentException
Byla zadána nepovolená hodnota parametru
● Např. chci nastavit zápornou velikost grafického tvaru
► IllegalStateException
V daném stavu objektu nelze metodu provést
● Např. otevřu soubor, přečtu pár vět, zavřu soubor a chci znovu přečíst větu
► NullPointerException
Byla vyvolána metoda instance, na níž ukazuje prázdný odkaz,
nebo byl předán nepovolený prázdný odkaz v parametru
► ArrayIndexOutOfBoundException
Byly zadány špatné meze pole, buď záporné nebo moc velké
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
32
Nejčastěji používané výjimky
2/2
► ConcurrentModificationException
V průběhu iterace byla změněna struktura kontejneru
● Např. byl do kontejneru přidán prvek
► NumberFormatException
Je požadován špatný převod řetězce na číslo či naopak
● Chci-li např. převést na číslo řetězec, který není číslem
● Častá chyba v metodách String.format či PrintStream.printf
► ClassCastException
Požadované přetypování není možné
► UnsupportedOperationException
Požadovaná operace není podporována
(např. chci přidat prvek do neměnného kontejneru)
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
33
Vaše jistota na trhu IT
Děkuji za pozornost
►Rudolf Pecinovský
http://vyuka.pecinovsky.cz/vse
mail: [email protected]
ICQ: 158 156 600
Slide 29
Vaše jistota na trhu IT
Výjimky
Rudolf Pecinovský
[email protected]
Vaše jistota na trhu IT
Obsah s odkazy
►Výjimky
►Výjimky kontrolované a nekontrolované
►Definice vlastních výjimek
Vaše jistota na trhu IT
Výjimky
►Výjimečné situace v programech
►Ošetření nestandardních situací v Javě
►Zpráva o výjimce
►Klíčová slova
►Činnost
►Vyvolání
Výjimečné situace v programech
► V každém programu je alespoň jedna chyba –
program na ni musí být připraven
► Starší programy
● Program vypsal chybové hlášení a ukončil činnost;
● V některých situacích (válcovací stolice, autopilot, …) nepřijatelné
● Funkce vrátí hodnotu signalizující chybu
● Programátor musí neustále testovat, co funkce vrací
● Knihovna měla pro tyto účely vyhrazenu speciální proměnnou,
do níž se v případě chyby zapsal její kód; nahlédnutím do proměnné
program zjistil kód poslední chyby
● Programátor musí neustále testovat, jaká je v proměnné hodnota
► Některé jazyky (Cobol, PL/1, …) proto přišly s koncepcí
ošetření nestandardních situací
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
4
Ošetření nestandardních situací v Javě
► Výjimečná událost =
problém, který brání dalšímu vykonávání části kódu
► Událost je výjimečná v tom, že na rozdíl od běžných problémů
nemá program k vyřešení situace dost informaci
► Program může při výskytu výjimečné události vyvolat výjimku
► Výjimka (exception)
objekt určený k přenosu informací o nastalém problému
z místa jeho vzniku do místa, kde bude problém řešen
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
5
Postup při vyvolání výjimky
1. Vytvoří se výjimka = objekt typu Throwable
(prakticky vždy instance některého z potomků)
2. Vytvořená výjimka se vyhodí =
přeruší se běh programu v místě, kde výjimka vznikla,
a začne se hledat místo, kde bude daná výjimka ošetřena
3. Ošetření výjimky (handler) by mělo uvést program do stavu,
v němž může jeho vykonávání pokračovat
► Výjimka „probublává“ programem z místa vyhození stále výše
a nenarazí-li cestou nikde na své ošetření,
zachytí ji virtuální stroj, který na standardní chybový výstup
vypíše zprávu o vzniku výjimky
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
6
Systémová zpráva o vzniku výjimky
Zpráva o vzniku výjimky spolu s názvem vlákna,
v němž k výjimce došlo (zde AWT-EventQueue-0)
Popis druhu výjimky (aritmetická výjimka dělení nulou)
Informace o místě, odkud byla volána metoda,
která vyvolala metodu, v níž došlo k vyhození výjimky
Informace o místě, odkud byla volána metoda,
v níž došlo k vyhození výjimky
Úplný název třídy včetně balíčku
Copyright © 2006, Rudolf Pecinovský
Název metody
VŠE – 05
Název souboru se
zdrojovým kódem
Číslo řádku zdrojáku,
kde došlo k výjimce
7
Klíčová slova související s výjimkami
► try (zkus)
Označuje blok kódu, v němž může dojít k výjimce
► throw (hoď)
Příkaz k vyhození výjimky;
musí být následován odkazem na existující instanci
► catch (chyť)
Blok ošetřující výjimku, která je zadána jako parametr
► finally (na konec)
Blok s povinnými závěrečnými akcemi nezávisejícími
na případném vzniku výjimky
► throws (hází)
Uvození seznamu výjimek vyhazovaných danou metodou
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
8
Vyvolání a ošetření výjimky v kódu
try {
//Kód, který může vyvolat výjimky
}
catch( Typ1 id1 ) {
//Ošetření výjimek typu Typ1
}
...
catch( TypN idN ) {
//ošetření výjimek typu TypN
}
finally {
//Kód, který se na závěr VŽDY provede
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
9
Náznak činnosti – řádný průběh
nedojde k vyvolání výjimky
= nedojde k chybě
try {
příkaz1();
příkaz2();
příkaz3();
}
catch ( xxxException e ) {
příkazProOšetřeníChyby();
}
Bloky catch
catch (…..
se přeskočí
finally {
ukončovacíPříkazy();
}
dalšíPříkaz();
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
12
Náznak činnosti – ošetřený výjimka
try {
příkaz1(); Při provádění metody příkaz2
dojde k ošetřené chybě
příkaz2();
příkaz3();
Byla vyhozena výjimka
tohoto typu nebo typu
}
některého z potomků
catch ( xxxException e ) {
příkazProOšetřeníChyby();
}
Ostatní bloky catch
catch (…..
se přeskočí
finally {
ukončovacíPříkazy();
}
dalšíPříkaz();
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
13
Náznak činnosti – neošetřená výjimka
Při provádění metody příkaz2
dojde k NEošetřené chybě
try {
příkaz1();
příkaz2();
příkaz3();
}
catch ( xxxException e ) {
příkazProOšetřeníChyby();
}
Ošetření nebylo nalezeno =>
catch (…..
provede se blok finally
a opouští se metoda
finally {
ukončovacíPříkazy();
}
dalšíPříkaz();
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
14
Vyvolání výjimky
public class Xyz implements Comparable
{
public bolean compareTo( Object o )
{
if( !(o instanceOf Xyz) )
throw new ClassCastException (
"\nPokus o porovnání s neporovnatelnou"
+ " instancí " + o );
//Zjištění, kdo je větší
return vysledek;
}
}
► Instanci nemusíme vytvářet až v příkazu throw,
můžeme ji vytvořit kdykoliv před tím a pak mu ji jen předat
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
15
Vaše jistota na trhu IT
Výjimky kontrolované a
nekontrolované
►Hierarchie výjimek
►Pořadí výjimek v blocích catch
►Metody generující výjimky
►Metody třídy Throwable
►Zřetězené výjimky
►Převod kontrolovaných na nekontrolované
Charakteristika
► Výjimky, které jsou potomky třídy RuntimeException
nebo Error označujeme jako nekontrolované (unchecked),
protože překladač nekontroluje, zda je na ně program připraven
► Ostatní výjimky označujeme jako kontrolované (checked),
protože překladač kontroluje dodržení pravidel:
● Každá metoda, která může vyhodit kontrolovanou výjimku,
se musí k této skutečnosti veřejně přihlásit
● Každé použití metody, která může vyhodit kontrolovanou výjimku,
musí být buď uzavřeno v bloku try…catch,
nebo se volající metoda musí přihlásit k tomu,
že může také vyhodit danou kontrolovanou výjimku
► Nekontrolované výjimky ohlašují chyby v programu,
kontrolované výjimky očekávatelné situace,
na jejichž výskyt má být program připraven
a měl by na ně umět reagovat
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
17
Hierarchie výjimek
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
18
Pořadí výjimek v blocích catch
► Třída NumberFormatException
je potomkem třídy RuntimeException
try {
Syntaktická chyba,
......
na druhý blok catch nikdy nedojde
}
catch (RuntimeException e) {
.........
}
Obrácené pořadí bloků catch
catch (NumberFormatException e){
vše vyřeší
........
try {
}
......
}
catch (NumberFormatException e) {
.........
}
catch (RuntimeException e){
........
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
19
Metody generující výjimky
► Java vyžaduje, aby programy, které používají metody
schopné vyvolat kontrolované výjimky,
byly o této schopnosti používaných metod informovány =>
pak vědí, které výjimku musí umět zachytit a ošetřit
► Všechny kontrolované výjimky, které může metoda vyhodit,
musí deklarovat v hlavičce za klíčovým slovem throws
► Deklarace vyhazování nekontrolovaných výjimek není povinná
public void metoda()
throws KontrolovanáVýjimka1,
KontrolovanáVýjimka2
{
// Tělo metody
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
20
Metody třídy Throwable
► String getMessage()
Vrátí zprávu popisující danou výjimku
► String toString()
Vrátí název třídy výjimky následovaný případnou zprávou
► void printStackTrace()
Vytiskne toString() následovaný sadou informací o volající
posloupnosti, která vedla k vzniku výjimky
► Throwable fillInStackTrace()
Připraví nové informace o volací posloupnosti
vedoucí k místu zavolání této metody
► StackTraceElement[] getStackTrace()
Vrátí uchované informace o volací posloupnosti dané výjimky
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
21
Zřetězené výjimky
► V některých situacích je vhodné v rámci ošetření výjimky vyvolat
jinou výjimku, a přitom umožnit zjistit,
která výjimka byla prvotním hybatelem celé akce
► Řada výjimek má mezi svými konstruktory i takové,
které akceptují jako poslední parametr
odkaz na výjimku, jež byla příčinou vyvolání dané výjimky
► Chce-li se program zeptat výjimky na výjimku, která ji způsobila,
použije metodu
public Throwable getCause()
► Ve zprávě o vyvolání výjimky jsou místa, kde byla jedna výjimka
nahrazena jinou, označována textem caused by:
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
22
Ukázka výpisu při zřetězení výjimek
HighLevelException: MidLevelException: LowLevelException
at Junk.a(Junk.java:13)
at Junk.main(Junk.java:4)
Caused by: MidLevelException: LowLevelException
at Junk.c(Junk.java:23)
at Junk.b(Junk.java:17)
at Junk.a(Junk.java:11)
... 1 more
Caused by: LowLevelException
at Junk.e(Junk.java:30)
at Junk.d(Junk.java:27)
at Junk.c(Junk.java:21)
... 3 more
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
23
Převod kontrolovaných na nekontrolované
► Ošetřování kontrolovaných výjimek obtěžuje
► Víme-li, že k dané výjimce nejspíš nedojde
a ošetřujeme-li ji pouze proto, že na tom překladač trvá,
můžeme pro případ, že by k výjimce přece jenom došlo
zaměnit kontrolovanou výjimku za nekontrolovanou
public void prevod( String s ) {
try {
prověř( s );
} catch( Exception ex ) {
throw new RuntimeException( " Neprověřeno! ", ex );
}
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
24
Vaše jistota na trhu IT
Definice vlastních výjimek
►Hierarchie výjimek
►Pořadí výjimek v blocích catch
►Metody generující výjimky
►Metody třídy Throwable
►Vlastní výjimky
►Zásady správného používání výjimek
Definice vlastních výjimek
► Výjimky jsou zcela běžné třídy;
považujeme-li to proto za vhodné, můžeme definovat i vlastní
► Před definicí nové výjimky bychom si měli ujasnit,
bude-li kontrolovaná či nekontrolovaná;
podle toho definujeme jejího předka
► Název výjimek končí dle konvencí slovem Exception
před nímž je naznačena podstata dané výjimky
● IllegalArgumetnException
● NoSuchMethodException
● BadStringOperationException
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
26
Příklad vlastní kontrolované výjimky
public class VelkýPrůšvihException
extends Exception
{
public VelkýPrůšvihException() {};
public VelkýPrůšvihException( String zpráva ) {
super( zpráva );
}
public VelkýPrůšvihException(String zpráva,
Throwable původce ) {
super( zpráva, původce );
}
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
27
Test správného vyhození výjimky
► Na vytvářených programech je třeba otestovat i to,
že v definovaných situacích vyhodí požadovanou výjimku
public void testVyhozeníVýjimky()
{
try {
metodaKteráMáVyhoditVýjimku();
} catch ( VelkýPrůšvihException vpe ) {
return;
}
fail( "Nebyla vyhozena výjimka VelkýPrůšvihException" );
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
28
Zásady správného používání výjimek
1/2
Neignorujte
výjimky
try {
//Nějaký kód
}
catch(Exception e){}
► Výjimky, o nichž víte, že nemohou nastat,
převeďte na nekontrolované pro případ,
že by v budoucích verzích programu nastat mohly
► Při ošetřování výjimek, které nastat mohou,
ale nemají vliv na chod programu,
vložte do těla ošetření alespoň vysvětlující komentář
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
29
Zásady správného používání výjimek
2/2
► Používejte výjimky pouze k ošetření výjimečných stavů
► Kontrolované výjimky používejte u stavů, z nichž se lze zotavit,
jinak použijte výjimky nekontrolované
► Vyhýbejte se zbytečnému používání kontrolovaných výjimek
● Programátory ošetřování kontrolovaných výjimek obtěžuje
a mají pak tendenci je ošetřovat prázdným blokem catch
► Dávejte přednost standardním výjimkám,
vyvolávejte výjimky odpovídající dané abstrakci
● Programátoři by měli z názvu výjimky poznat, co se stalo
● Standardní výjimky mají všeobecně známý význam
► Snažte se o atomičnost selhání; i po vyhození výjimky
by měl být objekt v dobře definovaném stavu
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
30
Zásady správného používání výjimek
3/2
► Doplňujte výjimky zprávami,
výjimka by sama měla poskytnout dostatek informací
a neměla by programátora nutit k podrobnější analýze programu
► Dokumentujte vyvolávané výjimky v dokumentačních
komentářích pomocí značky @throws
► Nedělejte bloky try zbytečně velké,
kód uvnitř těchto bloků se neoptimalizuje
► Umíte-li výjimku v metodě ošetřit, udělejte to
► Detekuje-li se chyba v jedné metodě a má se ošetřit v jiné
(stejné či jiné instance), použijte výjimku.
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
31
Nejčastěji používané výjimky
1/2
► IllegalArgumentException
Byla zadána nepovolená hodnota parametru
● Např. chci nastavit zápornou velikost grafického tvaru
► IllegalStateException
V daném stavu objektu nelze metodu provést
● Např. otevřu soubor, přečtu pár vět, zavřu soubor a chci znovu přečíst větu
► NullPointerException
Byla vyvolána metoda instance, na níž ukazuje prázdný odkaz,
nebo byl předán nepovolený prázdný odkaz v parametru
► ArrayIndexOutOfBoundException
Byly zadány špatné meze pole, buď záporné nebo moc velké
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
32
Nejčastěji používané výjimky
2/2
► ConcurrentModificationException
V průběhu iterace byla změněna struktura kontejneru
● Např. byl do kontejneru přidán prvek
► NumberFormatException
Je požadován špatný převod řetězce na číslo či naopak
● Chci-li např. převést na číslo řetězec, který není číslem
● Častá chyba v metodách String.format či PrintStream.printf
► ClassCastException
Požadované přetypování není možné
► UnsupportedOperationException
Požadovaná operace není podporována
(např. chci přidat prvek do neměnného kontejneru)
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
33
Vaše jistota na trhu IT
Děkuji za pozornost
►Rudolf Pecinovský
http://vyuka.pecinovsky.cz/vse
mail: [email protected]
ICQ: 158 156 600
Slide 30
Vaše jistota na trhu IT
Výjimky
Rudolf Pecinovský
[email protected]
Vaše jistota na trhu IT
Obsah s odkazy
►Výjimky
►Výjimky kontrolované a nekontrolované
►Definice vlastních výjimek
Vaše jistota na trhu IT
Výjimky
►Výjimečné situace v programech
►Ošetření nestandardních situací v Javě
►Zpráva o výjimce
►Klíčová slova
►Činnost
►Vyvolání
Výjimečné situace v programech
► V každém programu je alespoň jedna chyba –
program na ni musí být připraven
► Starší programy
● Program vypsal chybové hlášení a ukončil činnost;
● V některých situacích (válcovací stolice, autopilot, …) nepřijatelné
● Funkce vrátí hodnotu signalizující chybu
● Programátor musí neustále testovat, co funkce vrací
● Knihovna měla pro tyto účely vyhrazenu speciální proměnnou,
do níž se v případě chyby zapsal její kód; nahlédnutím do proměnné
program zjistil kód poslední chyby
● Programátor musí neustále testovat, jaká je v proměnné hodnota
► Některé jazyky (Cobol, PL/1, …) proto přišly s koncepcí
ošetření nestandardních situací
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
4
Ošetření nestandardních situací v Javě
► Výjimečná událost =
problém, který brání dalšímu vykonávání části kódu
► Událost je výjimečná v tom, že na rozdíl od běžných problémů
nemá program k vyřešení situace dost informaci
► Program může při výskytu výjimečné události vyvolat výjimku
► Výjimka (exception)
objekt určený k přenosu informací o nastalém problému
z místa jeho vzniku do místa, kde bude problém řešen
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
5
Postup při vyvolání výjimky
1. Vytvoří se výjimka = objekt typu Throwable
(prakticky vždy instance některého z potomků)
2. Vytvořená výjimka se vyhodí =
přeruší se běh programu v místě, kde výjimka vznikla,
a začne se hledat místo, kde bude daná výjimka ošetřena
3. Ošetření výjimky (handler) by mělo uvést program do stavu,
v němž může jeho vykonávání pokračovat
► Výjimka „probublává“ programem z místa vyhození stále výše
a nenarazí-li cestou nikde na své ošetření,
zachytí ji virtuální stroj, který na standardní chybový výstup
vypíše zprávu o vzniku výjimky
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
6
Systémová zpráva o vzniku výjimky
Zpráva o vzniku výjimky spolu s názvem vlákna,
v němž k výjimce došlo (zde AWT-EventQueue-0)
Popis druhu výjimky (aritmetická výjimka dělení nulou)
Informace o místě, odkud byla volána metoda,
která vyvolala metodu, v níž došlo k vyhození výjimky
Informace o místě, odkud byla volána metoda,
v níž došlo k vyhození výjimky
Úplný název třídy včetně balíčku
Copyright © 2006, Rudolf Pecinovský
Název metody
VŠE – 05
Název souboru se
zdrojovým kódem
Číslo řádku zdrojáku,
kde došlo k výjimce
7
Klíčová slova související s výjimkami
► try (zkus)
Označuje blok kódu, v němž může dojít k výjimce
► throw (hoď)
Příkaz k vyhození výjimky;
musí být následován odkazem na existující instanci
► catch (chyť)
Blok ošetřující výjimku, která je zadána jako parametr
► finally (na konec)
Blok s povinnými závěrečnými akcemi nezávisejícími
na případném vzniku výjimky
► throws (hází)
Uvození seznamu výjimek vyhazovaných danou metodou
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
8
Vyvolání a ošetření výjimky v kódu
try {
//Kód, který může vyvolat výjimky
}
catch( Typ1 id1 ) {
//Ošetření výjimek typu Typ1
}
...
catch( TypN idN ) {
//ošetření výjimek typu TypN
}
finally {
//Kód, který se na závěr VŽDY provede
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
9
Náznak činnosti – řádný průběh
nedojde k vyvolání výjimky
= nedojde k chybě
try {
příkaz1();
příkaz2();
příkaz3();
}
catch ( xxxException e ) {
příkazProOšetřeníChyby();
}
Bloky catch
catch (…..
se přeskočí
finally {
ukončovacíPříkazy();
}
dalšíPříkaz();
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
12
Náznak činnosti – ošetřený výjimka
try {
příkaz1(); Při provádění metody příkaz2
dojde k ošetřené chybě
příkaz2();
příkaz3();
Byla vyhozena výjimka
tohoto typu nebo typu
}
některého z potomků
catch ( xxxException e ) {
příkazProOšetřeníChyby();
}
Ostatní bloky catch
catch (…..
se přeskočí
finally {
ukončovacíPříkazy();
}
dalšíPříkaz();
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
13
Náznak činnosti – neošetřená výjimka
Při provádění metody příkaz2
dojde k NEošetřené chybě
try {
příkaz1();
příkaz2();
příkaz3();
}
catch ( xxxException e ) {
příkazProOšetřeníChyby();
}
Ošetření nebylo nalezeno =>
catch (…..
provede se blok finally
a opouští se metoda
finally {
ukončovacíPříkazy();
}
dalšíPříkaz();
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
14
Vyvolání výjimky
public class Xyz implements Comparable
{
public bolean compareTo( Object o )
{
if( !(o instanceOf Xyz) )
throw new ClassCastException (
"\nPokus o porovnání s neporovnatelnou"
+ " instancí " + o );
//Zjištění, kdo je větší
return vysledek;
}
}
► Instanci nemusíme vytvářet až v příkazu throw,
můžeme ji vytvořit kdykoliv před tím a pak mu ji jen předat
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
15
Vaše jistota na trhu IT
Výjimky kontrolované a
nekontrolované
►Hierarchie výjimek
►Pořadí výjimek v blocích catch
►Metody generující výjimky
►Metody třídy Throwable
►Zřetězené výjimky
►Převod kontrolovaných na nekontrolované
Charakteristika
► Výjimky, které jsou potomky třídy RuntimeException
nebo Error označujeme jako nekontrolované (unchecked),
protože překladač nekontroluje, zda je na ně program připraven
► Ostatní výjimky označujeme jako kontrolované (checked),
protože překladač kontroluje dodržení pravidel:
● Každá metoda, která může vyhodit kontrolovanou výjimku,
se musí k této skutečnosti veřejně přihlásit
● Každé použití metody, která může vyhodit kontrolovanou výjimku,
musí být buď uzavřeno v bloku try…catch,
nebo se volající metoda musí přihlásit k tomu,
že může také vyhodit danou kontrolovanou výjimku
► Nekontrolované výjimky ohlašují chyby v programu,
kontrolované výjimky očekávatelné situace,
na jejichž výskyt má být program připraven
a měl by na ně umět reagovat
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
17
Hierarchie výjimek
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
18
Pořadí výjimek v blocích catch
► Třída NumberFormatException
je potomkem třídy RuntimeException
try {
Syntaktická chyba,
......
na druhý blok catch nikdy nedojde
}
catch (RuntimeException e) {
.........
}
Obrácené pořadí bloků catch
catch (NumberFormatException e){
vše vyřeší
........
try {
}
......
}
catch (NumberFormatException e) {
.........
}
catch (RuntimeException e){
........
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
19
Metody generující výjimky
► Java vyžaduje, aby programy, které používají metody
schopné vyvolat kontrolované výjimky,
byly o této schopnosti používaných metod informovány =>
pak vědí, které výjimku musí umět zachytit a ošetřit
► Všechny kontrolované výjimky, které může metoda vyhodit,
musí deklarovat v hlavičce za klíčovým slovem throws
► Deklarace vyhazování nekontrolovaných výjimek není povinná
public void metoda()
throws KontrolovanáVýjimka1,
KontrolovanáVýjimka2
{
// Tělo metody
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
20
Metody třídy Throwable
► String getMessage()
Vrátí zprávu popisující danou výjimku
► String toString()
Vrátí název třídy výjimky následovaný případnou zprávou
► void printStackTrace()
Vytiskne toString() následovaný sadou informací o volající
posloupnosti, která vedla k vzniku výjimky
► Throwable fillInStackTrace()
Připraví nové informace o volací posloupnosti
vedoucí k místu zavolání této metody
► StackTraceElement[] getStackTrace()
Vrátí uchované informace o volací posloupnosti dané výjimky
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
21
Zřetězené výjimky
► V některých situacích je vhodné v rámci ošetření výjimky vyvolat
jinou výjimku, a přitom umožnit zjistit,
která výjimka byla prvotním hybatelem celé akce
► Řada výjimek má mezi svými konstruktory i takové,
které akceptují jako poslední parametr
odkaz na výjimku, jež byla příčinou vyvolání dané výjimky
► Chce-li se program zeptat výjimky na výjimku, která ji způsobila,
použije metodu
public Throwable getCause()
► Ve zprávě o vyvolání výjimky jsou místa, kde byla jedna výjimka
nahrazena jinou, označována textem caused by:
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
22
Ukázka výpisu při zřetězení výjimek
HighLevelException: MidLevelException: LowLevelException
at Junk.a(Junk.java:13)
at Junk.main(Junk.java:4)
Caused by: MidLevelException: LowLevelException
at Junk.c(Junk.java:23)
at Junk.b(Junk.java:17)
at Junk.a(Junk.java:11)
... 1 more
Caused by: LowLevelException
at Junk.e(Junk.java:30)
at Junk.d(Junk.java:27)
at Junk.c(Junk.java:21)
... 3 more
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
23
Převod kontrolovaných na nekontrolované
► Ošetřování kontrolovaných výjimek obtěžuje
► Víme-li, že k dané výjimce nejspíš nedojde
a ošetřujeme-li ji pouze proto, že na tom překladač trvá,
můžeme pro případ, že by k výjimce přece jenom došlo
zaměnit kontrolovanou výjimku za nekontrolovanou
public void prevod( String s ) {
try {
prověř( s );
} catch( Exception ex ) {
throw new RuntimeException( " Neprověřeno! ", ex );
}
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
24
Vaše jistota na trhu IT
Definice vlastních výjimek
►Hierarchie výjimek
►Pořadí výjimek v blocích catch
►Metody generující výjimky
►Metody třídy Throwable
►Vlastní výjimky
►Zásady správného používání výjimek
Definice vlastních výjimek
► Výjimky jsou zcela běžné třídy;
považujeme-li to proto za vhodné, můžeme definovat i vlastní
► Před definicí nové výjimky bychom si měli ujasnit,
bude-li kontrolovaná či nekontrolovaná;
podle toho definujeme jejího předka
► Název výjimek končí dle konvencí slovem Exception
před nímž je naznačena podstata dané výjimky
● IllegalArgumetnException
● NoSuchMethodException
● BadStringOperationException
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
26
Příklad vlastní kontrolované výjimky
public class VelkýPrůšvihException
extends Exception
{
public VelkýPrůšvihException() {};
public VelkýPrůšvihException( String zpráva ) {
super( zpráva );
}
public VelkýPrůšvihException(String zpráva,
Throwable původce ) {
super( zpráva, původce );
}
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
27
Test správného vyhození výjimky
► Na vytvářených programech je třeba otestovat i to,
že v definovaných situacích vyhodí požadovanou výjimku
public void testVyhozeníVýjimky()
{
try {
metodaKteráMáVyhoditVýjimku();
} catch ( VelkýPrůšvihException vpe ) {
return;
}
fail( "Nebyla vyhozena výjimka VelkýPrůšvihException" );
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
28
Zásady správného používání výjimek
1/2
Neignorujte
výjimky
try {
//Nějaký kód
}
catch(Exception e){}
► Výjimky, o nichž víte, že nemohou nastat,
převeďte na nekontrolované pro případ,
že by v budoucích verzích programu nastat mohly
► Při ošetřování výjimek, které nastat mohou,
ale nemají vliv na chod programu,
vložte do těla ošetření alespoň vysvětlující komentář
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
29
Zásady správného používání výjimek
2/2
► Používejte výjimky pouze k ošetření výjimečných stavů
► Kontrolované výjimky používejte u stavů, z nichž se lze zotavit,
jinak použijte výjimky nekontrolované
► Vyhýbejte se zbytečnému používání kontrolovaných výjimek
● Programátory ošetřování kontrolovaných výjimek obtěžuje
a mají pak tendenci je ošetřovat prázdným blokem catch
► Dávejte přednost standardním výjimkám,
vyvolávejte výjimky odpovídající dané abstrakci
● Programátoři by měli z názvu výjimky poznat, co se stalo
● Standardní výjimky mají všeobecně známý význam
► Snažte se o atomičnost selhání; i po vyhození výjimky
by měl být objekt v dobře definovaném stavu
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
30
Zásady správného používání výjimek
3/2
► Doplňujte výjimky zprávami,
výjimka by sama měla poskytnout dostatek informací
a neměla by programátora nutit k podrobnější analýze programu
► Dokumentujte vyvolávané výjimky v dokumentačních
komentářích pomocí značky @throws
► Nedělejte bloky try zbytečně velké,
kód uvnitř těchto bloků se neoptimalizuje
► Umíte-li výjimku v metodě ošetřit, udělejte to
► Detekuje-li se chyba v jedné metodě a má se ošetřit v jiné
(stejné či jiné instance), použijte výjimku.
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
31
Nejčastěji používané výjimky
1/2
► IllegalArgumentException
Byla zadána nepovolená hodnota parametru
● Např. chci nastavit zápornou velikost grafického tvaru
► IllegalStateException
V daném stavu objektu nelze metodu provést
● Např. otevřu soubor, přečtu pár vět, zavřu soubor a chci znovu přečíst větu
► NullPointerException
Byla vyvolána metoda instance, na níž ukazuje prázdný odkaz,
nebo byl předán nepovolený prázdný odkaz v parametru
► ArrayIndexOutOfBoundException
Byly zadány špatné meze pole, buď záporné nebo moc velké
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
32
Nejčastěji používané výjimky
2/2
► ConcurrentModificationException
V průběhu iterace byla změněna struktura kontejneru
● Např. byl do kontejneru přidán prvek
► NumberFormatException
Je požadován špatný převod řetězce na číslo či naopak
● Chci-li např. převést na číslo řetězec, který není číslem
● Častá chyba v metodách String.format či PrintStream.printf
► ClassCastException
Požadované přetypování není možné
► UnsupportedOperationException
Požadovaná operace není podporována
(např. chci přidat prvek do neměnného kontejneru)
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
33
Vaše jistota na trhu IT
Děkuji za pozornost
►Rudolf Pecinovský
http://vyuka.pecinovsky.cz/vse
mail: [email protected]
ICQ: 158 156 600
Slide 31
Vaše jistota na trhu IT
Výjimky
Rudolf Pecinovský
[email protected]
Vaše jistota na trhu IT
Obsah s odkazy
►Výjimky
►Výjimky kontrolované a nekontrolované
►Definice vlastních výjimek
Vaše jistota na trhu IT
Výjimky
►Výjimečné situace v programech
►Ošetření nestandardních situací v Javě
►Zpráva o výjimce
►Klíčová slova
►Činnost
►Vyvolání
Výjimečné situace v programech
► V každém programu je alespoň jedna chyba –
program na ni musí být připraven
► Starší programy
● Program vypsal chybové hlášení a ukončil činnost;
● V některých situacích (válcovací stolice, autopilot, …) nepřijatelné
● Funkce vrátí hodnotu signalizující chybu
● Programátor musí neustále testovat, co funkce vrací
● Knihovna měla pro tyto účely vyhrazenu speciální proměnnou,
do níž se v případě chyby zapsal její kód; nahlédnutím do proměnné
program zjistil kód poslední chyby
● Programátor musí neustále testovat, jaká je v proměnné hodnota
► Některé jazyky (Cobol, PL/1, …) proto přišly s koncepcí
ošetření nestandardních situací
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
4
Ošetření nestandardních situací v Javě
► Výjimečná událost =
problém, který brání dalšímu vykonávání části kódu
► Událost je výjimečná v tom, že na rozdíl od běžných problémů
nemá program k vyřešení situace dost informaci
► Program může při výskytu výjimečné události vyvolat výjimku
► Výjimka (exception)
objekt určený k přenosu informací o nastalém problému
z místa jeho vzniku do místa, kde bude problém řešen
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
5
Postup při vyvolání výjimky
1. Vytvoří se výjimka = objekt typu Throwable
(prakticky vždy instance některého z potomků)
2. Vytvořená výjimka se vyhodí =
přeruší se běh programu v místě, kde výjimka vznikla,
a začne se hledat místo, kde bude daná výjimka ošetřena
3. Ošetření výjimky (handler) by mělo uvést program do stavu,
v němž může jeho vykonávání pokračovat
► Výjimka „probublává“ programem z místa vyhození stále výše
a nenarazí-li cestou nikde na své ošetření,
zachytí ji virtuální stroj, který na standardní chybový výstup
vypíše zprávu o vzniku výjimky
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
6
Systémová zpráva o vzniku výjimky
Zpráva o vzniku výjimky spolu s názvem vlákna,
v němž k výjimce došlo (zde AWT-EventQueue-0)
Popis druhu výjimky (aritmetická výjimka dělení nulou)
Informace o místě, odkud byla volána metoda,
která vyvolala metodu, v níž došlo k vyhození výjimky
Informace o místě, odkud byla volána metoda,
v níž došlo k vyhození výjimky
Úplný název třídy včetně balíčku
Copyright © 2006, Rudolf Pecinovský
Název metody
VŠE – 05
Název souboru se
zdrojovým kódem
Číslo řádku zdrojáku,
kde došlo k výjimce
7
Klíčová slova související s výjimkami
► try (zkus)
Označuje blok kódu, v němž může dojít k výjimce
► throw (hoď)
Příkaz k vyhození výjimky;
musí být následován odkazem na existující instanci
► catch (chyť)
Blok ošetřující výjimku, která je zadána jako parametr
► finally (na konec)
Blok s povinnými závěrečnými akcemi nezávisejícími
na případném vzniku výjimky
► throws (hází)
Uvození seznamu výjimek vyhazovaných danou metodou
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
8
Vyvolání a ošetření výjimky v kódu
try {
//Kód, který může vyvolat výjimky
}
catch( Typ1 id1 ) {
//Ošetření výjimek typu Typ1
}
...
catch( TypN idN ) {
//ošetření výjimek typu TypN
}
finally {
//Kód, který se na závěr VŽDY provede
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
9
Náznak činnosti – řádný průběh
nedojde k vyvolání výjimky
= nedojde k chybě
try {
příkaz1();
příkaz2();
příkaz3();
}
catch ( xxxException e ) {
příkazProOšetřeníChyby();
}
Bloky catch
catch (…..
se přeskočí
finally {
ukončovacíPříkazy();
}
dalšíPříkaz();
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
12
Náznak činnosti – ošetřený výjimka
try {
příkaz1(); Při provádění metody příkaz2
dojde k ošetřené chybě
příkaz2();
příkaz3();
Byla vyhozena výjimka
tohoto typu nebo typu
}
některého z potomků
catch ( xxxException e ) {
příkazProOšetřeníChyby();
}
Ostatní bloky catch
catch (…..
se přeskočí
finally {
ukončovacíPříkazy();
}
dalšíPříkaz();
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
13
Náznak činnosti – neošetřená výjimka
Při provádění metody příkaz2
dojde k NEošetřené chybě
try {
příkaz1();
příkaz2();
příkaz3();
}
catch ( xxxException e ) {
příkazProOšetřeníChyby();
}
Ošetření nebylo nalezeno =>
catch (…..
provede se blok finally
a opouští se metoda
finally {
ukončovacíPříkazy();
}
dalšíPříkaz();
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
14
Vyvolání výjimky
public class Xyz implements Comparable
{
public bolean compareTo( Object o )
{
if( !(o instanceOf Xyz) )
throw new ClassCastException (
"\nPokus o porovnání s neporovnatelnou"
+ " instancí " + o );
//Zjištění, kdo je větší
return vysledek;
}
}
► Instanci nemusíme vytvářet až v příkazu throw,
můžeme ji vytvořit kdykoliv před tím a pak mu ji jen předat
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
15
Vaše jistota na trhu IT
Výjimky kontrolované a
nekontrolované
►Hierarchie výjimek
►Pořadí výjimek v blocích catch
►Metody generující výjimky
►Metody třídy Throwable
►Zřetězené výjimky
►Převod kontrolovaných na nekontrolované
Charakteristika
► Výjimky, které jsou potomky třídy RuntimeException
nebo Error označujeme jako nekontrolované (unchecked),
protože překladač nekontroluje, zda je na ně program připraven
► Ostatní výjimky označujeme jako kontrolované (checked),
protože překladač kontroluje dodržení pravidel:
● Každá metoda, která může vyhodit kontrolovanou výjimku,
se musí k této skutečnosti veřejně přihlásit
● Každé použití metody, která může vyhodit kontrolovanou výjimku,
musí být buď uzavřeno v bloku try…catch,
nebo se volající metoda musí přihlásit k tomu,
že může také vyhodit danou kontrolovanou výjimku
► Nekontrolované výjimky ohlašují chyby v programu,
kontrolované výjimky očekávatelné situace,
na jejichž výskyt má být program připraven
a měl by na ně umět reagovat
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
17
Hierarchie výjimek
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
18
Pořadí výjimek v blocích catch
► Třída NumberFormatException
je potomkem třídy RuntimeException
try {
Syntaktická chyba,
......
na druhý blok catch nikdy nedojde
}
catch (RuntimeException e) {
.........
}
Obrácené pořadí bloků catch
catch (NumberFormatException e){
vše vyřeší
........
try {
}
......
}
catch (NumberFormatException e) {
.........
}
catch (RuntimeException e){
........
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
19
Metody generující výjimky
► Java vyžaduje, aby programy, které používají metody
schopné vyvolat kontrolované výjimky,
byly o této schopnosti používaných metod informovány =>
pak vědí, které výjimku musí umět zachytit a ošetřit
► Všechny kontrolované výjimky, které může metoda vyhodit,
musí deklarovat v hlavičce za klíčovým slovem throws
► Deklarace vyhazování nekontrolovaných výjimek není povinná
public void metoda()
throws KontrolovanáVýjimka1,
KontrolovanáVýjimka2
{
// Tělo metody
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
20
Metody třídy Throwable
► String getMessage()
Vrátí zprávu popisující danou výjimku
► String toString()
Vrátí název třídy výjimky následovaný případnou zprávou
► void printStackTrace()
Vytiskne toString() následovaný sadou informací o volající
posloupnosti, která vedla k vzniku výjimky
► Throwable fillInStackTrace()
Připraví nové informace o volací posloupnosti
vedoucí k místu zavolání této metody
► StackTraceElement[] getStackTrace()
Vrátí uchované informace o volací posloupnosti dané výjimky
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
21
Zřetězené výjimky
► V některých situacích je vhodné v rámci ošetření výjimky vyvolat
jinou výjimku, a přitom umožnit zjistit,
která výjimka byla prvotním hybatelem celé akce
► Řada výjimek má mezi svými konstruktory i takové,
které akceptují jako poslední parametr
odkaz na výjimku, jež byla příčinou vyvolání dané výjimky
► Chce-li se program zeptat výjimky na výjimku, která ji způsobila,
použije metodu
public Throwable getCause()
► Ve zprávě o vyvolání výjimky jsou místa, kde byla jedna výjimka
nahrazena jinou, označována textem caused by:
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
22
Ukázka výpisu při zřetězení výjimek
HighLevelException: MidLevelException: LowLevelException
at Junk.a(Junk.java:13)
at Junk.main(Junk.java:4)
Caused by: MidLevelException: LowLevelException
at Junk.c(Junk.java:23)
at Junk.b(Junk.java:17)
at Junk.a(Junk.java:11)
... 1 more
Caused by: LowLevelException
at Junk.e(Junk.java:30)
at Junk.d(Junk.java:27)
at Junk.c(Junk.java:21)
... 3 more
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
23
Převod kontrolovaných na nekontrolované
► Ošetřování kontrolovaných výjimek obtěžuje
► Víme-li, že k dané výjimce nejspíš nedojde
a ošetřujeme-li ji pouze proto, že na tom překladač trvá,
můžeme pro případ, že by k výjimce přece jenom došlo
zaměnit kontrolovanou výjimku za nekontrolovanou
public void prevod( String s ) {
try {
prověř( s );
} catch( Exception ex ) {
throw new RuntimeException( " Neprověřeno! ", ex );
}
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
24
Vaše jistota na trhu IT
Definice vlastních výjimek
►Hierarchie výjimek
►Pořadí výjimek v blocích catch
►Metody generující výjimky
►Metody třídy Throwable
►Vlastní výjimky
►Zásady správného používání výjimek
Definice vlastních výjimek
► Výjimky jsou zcela běžné třídy;
považujeme-li to proto za vhodné, můžeme definovat i vlastní
► Před definicí nové výjimky bychom si měli ujasnit,
bude-li kontrolovaná či nekontrolovaná;
podle toho definujeme jejího předka
► Název výjimek končí dle konvencí slovem Exception
před nímž je naznačena podstata dané výjimky
● IllegalArgumetnException
● NoSuchMethodException
● BadStringOperationException
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
26
Příklad vlastní kontrolované výjimky
public class VelkýPrůšvihException
extends Exception
{
public VelkýPrůšvihException() {};
public VelkýPrůšvihException( String zpráva ) {
super( zpráva );
}
public VelkýPrůšvihException(String zpráva,
Throwable původce ) {
super( zpráva, původce );
}
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
27
Test správného vyhození výjimky
► Na vytvářených programech je třeba otestovat i to,
že v definovaných situacích vyhodí požadovanou výjimku
public void testVyhozeníVýjimky()
{
try {
metodaKteráMáVyhoditVýjimku();
} catch ( VelkýPrůšvihException vpe ) {
return;
}
fail( "Nebyla vyhozena výjimka VelkýPrůšvihException" );
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
28
Zásady správného používání výjimek
1/2
Neignorujte
výjimky
try {
//Nějaký kód
}
catch(Exception e){}
► Výjimky, o nichž víte, že nemohou nastat,
převeďte na nekontrolované pro případ,
že by v budoucích verzích programu nastat mohly
► Při ošetřování výjimek, které nastat mohou,
ale nemají vliv na chod programu,
vložte do těla ošetření alespoň vysvětlující komentář
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
29
Zásady správného používání výjimek
2/2
► Používejte výjimky pouze k ošetření výjimečných stavů
► Kontrolované výjimky používejte u stavů, z nichž se lze zotavit,
jinak použijte výjimky nekontrolované
► Vyhýbejte se zbytečnému používání kontrolovaných výjimek
● Programátory ošetřování kontrolovaných výjimek obtěžuje
a mají pak tendenci je ošetřovat prázdným blokem catch
► Dávejte přednost standardním výjimkám,
vyvolávejte výjimky odpovídající dané abstrakci
● Programátoři by měli z názvu výjimky poznat, co se stalo
● Standardní výjimky mají všeobecně známý význam
► Snažte se o atomičnost selhání; i po vyhození výjimky
by měl být objekt v dobře definovaném stavu
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
30
Zásady správného používání výjimek
3/2
► Doplňujte výjimky zprávami,
výjimka by sama měla poskytnout dostatek informací
a neměla by programátora nutit k podrobnější analýze programu
► Dokumentujte vyvolávané výjimky v dokumentačních
komentářích pomocí značky @throws
► Nedělejte bloky try zbytečně velké,
kód uvnitř těchto bloků se neoptimalizuje
► Umíte-li výjimku v metodě ošetřit, udělejte to
► Detekuje-li se chyba v jedné metodě a má se ošetřit v jiné
(stejné či jiné instance), použijte výjimku.
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
31
Nejčastěji používané výjimky
1/2
► IllegalArgumentException
Byla zadána nepovolená hodnota parametru
● Např. chci nastavit zápornou velikost grafického tvaru
► IllegalStateException
V daném stavu objektu nelze metodu provést
● Např. otevřu soubor, přečtu pár vět, zavřu soubor a chci znovu přečíst větu
► NullPointerException
Byla vyvolána metoda instance, na níž ukazuje prázdný odkaz,
nebo byl předán nepovolený prázdný odkaz v parametru
► ArrayIndexOutOfBoundException
Byly zadány špatné meze pole, buď záporné nebo moc velké
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
32
Nejčastěji používané výjimky
2/2
► ConcurrentModificationException
V průběhu iterace byla změněna struktura kontejneru
● Např. byl do kontejneru přidán prvek
► NumberFormatException
Je požadován špatný převod řetězce na číslo či naopak
● Chci-li např. převést na číslo řetězec, který není číslem
● Častá chyba v metodách String.format či PrintStream.printf
► ClassCastException
Požadované přetypování není možné
► UnsupportedOperationException
Požadovaná operace není podporována
(např. chci přidat prvek do neměnného kontejneru)
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
33
Vaše jistota na trhu IT
Děkuji za pozornost
►Rudolf Pecinovský
http://vyuka.pecinovsky.cz/vse
mail: [email protected]
ICQ: 158 156 600
Slide 32
Vaše jistota na trhu IT
Výjimky
Rudolf Pecinovský
[email protected]
Vaše jistota na trhu IT
Obsah s odkazy
►Výjimky
►Výjimky kontrolované a nekontrolované
►Definice vlastních výjimek
Vaše jistota na trhu IT
Výjimky
►Výjimečné situace v programech
►Ošetření nestandardních situací v Javě
►Zpráva o výjimce
►Klíčová slova
►Činnost
►Vyvolání
Výjimečné situace v programech
► V každém programu je alespoň jedna chyba –
program na ni musí být připraven
► Starší programy
● Program vypsal chybové hlášení a ukončil činnost;
● V některých situacích (válcovací stolice, autopilot, …) nepřijatelné
● Funkce vrátí hodnotu signalizující chybu
● Programátor musí neustále testovat, co funkce vrací
● Knihovna měla pro tyto účely vyhrazenu speciální proměnnou,
do níž se v případě chyby zapsal její kód; nahlédnutím do proměnné
program zjistil kód poslední chyby
● Programátor musí neustále testovat, jaká je v proměnné hodnota
► Některé jazyky (Cobol, PL/1, …) proto přišly s koncepcí
ošetření nestandardních situací
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
4
Ošetření nestandardních situací v Javě
► Výjimečná událost =
problém, který brání dalšímu vykonávání části kódu
► Událost je výjimečná v tom, že na rozdíl od běžných problémů
nemá program k vyřešení situace dost informaci
► Program může při výskytu výjimečné události vyvolat výjimku
► Výjimka (exception)
objekt určený k přenosu informací o nastalém problému
z místa jeho vzniku do místa, kde bude problém řešen
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
5
Postup při vyvolání výjimky
1. Vytvoří se výjimka = objekt typu Throwable
(prakticky vždy instance některého z potomků)
2. Vytvořená výjimka se vyhodí =
přeruší se běh programu v místě, kde výjimka vznikla,
a začne se hledat místo, kde bude daná výjimka ošetřena
3. Ošetření výjimky (handler) by mělo uvést program do stavu,
v němž může jeho vykonávání pokračovat
► Výjimka „probublává“ programem z místa vyhození stále výše
a nenarazí-li cestou nikde na své ošetření,
zachytí ji virtuální stroj, který na standardní chybový výstup
vypíše zprávu o vzniku výjimky
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
6
Systémová zpráva o vzniku výjimky
Zpráva o vzniku výjimky spolu s názvem vlákna,
v němž k výjimce došlo (zde AWT-EventQueue-0)
Popis druhu výjimky (aritmetická výjimka dělení nulou)
Informace o místě, odkud byla volána metoda,
která vyvolala metodu, v níž došlo k vyhození výjimky
Informace o místě, odkud byla volána metoda,
v níž došlo k vyhození výjimky
Úplný název třídy včetně balíčku
Copyright © 2006, Rudolf Pecinovský
Název metody
VŠE – 05
Název souboru se
zdrojovým kódem
Číslo řádku zdrojáku,
kde došlo k výjimce
7
Klíčová slova související s výjimkami
► try (zkus)
Označuje blok kódu, v němž může dojít k výjimce
► throw (hoď)
Příkaz k vyhození výjimky;
musí být následován odkazem na existující instanci
► catch (chyť)
Blok ošetřující výjimku, která je zadána jako parametr
► finally (na konec)
Blok s povinnými závěrečnými akcemi nezávisejícími
na případném vzniku výjimky
► throws (hází)
Uvození seznamu výjimek vyhazovaných danou metodou
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
8
Vyvolání a ošetření výjimky v kódu
try {
//Kód, který může vyvolat výjimky
}
catch( Typ1 id1 ) {
//Ošetření výjimek typu Typ1
}
...
catch( TypN idN ) {
//ošetření výjimek typu TypN
}
finally {
//Kód, který se na závěr VŽDY provede
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
9
Náznak činnosti – řádný průběh
nedojde k vyvolání výjimky
= nedojde k chybě
try {
příkaz1();
příkaz2();
příkaz3();
}
catch ( xxxException e ) {
příkazProOšetřeníChyby();
}
Bloky catch
catch (…..
se přeskočí
finally {
ukončovacíPříkazy();
}
dalšíPříkaz();
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
12
Náznak činnosti – ošetřený výjimka
try {
příkaz1(); Při provádění metody příkaz2
dojde k ošetřené chybě
příkaz2();
příkaz3();
Byla vyhozena výjimka
tohoto typu nebo typu
}
některého z potomků
catch ( xxxException e ) {
příkazProOšetřeníChyby();
}
Ostatní bloky catch
catch (…..
se přeskočí
finally {
ukončovacíPříkazy();
}
dalšíPříkaz();
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
13
Náznak činnosti – neošetřená výjimka
Při provádění metody příkaz2
dojde k NEošetřené chybě
try {
příkaz1();
příkaz2();
příkaz3();
}
catch ( xxxException e ) {
příkazProOšetřeníChyby();
}
Ošetření nebylo nalezeno =>
catch (…..
provede se blok finally
a opouští se metoda
finally {
ukončovacíPříkazy();
}
dalšíPříkaz();
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
14
Vyvolání výjimky
public class Xyz implements Comparable
{
public bolean compareTo( Object o )
{
if( !(o instanceOf Xyz) )
throw new ClassCastException (
"\nPokus o porovnání s neporovnatelnou"
+ " instancí " + o );
//Zjištění, kdo je větší
return vysledek;
}
}
► Instanci nemusíme vytvářet až v příkazu throw,
můžeme ji vytvořit kdykoliv před tím a pak mu ji jen předat
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
15
Vaše jistota na trhu IT
Výjimky kontrolované a
nekontrolované
►Hierarchie výjimek
►Pořadí výjimek v blocích catch
►Metody generující výjimky
►Metody třídy Throwable
►Zřetězené výjimky
►Převod kontrolovaných na nekontrolované
Charakteristika
► Výjimky, které jsou potomky třídy RuntimeException
nebo Error označujeme jako nekontrolované (unchecked),
protože překladač nekontroluje, zda je na ně program připraven
► Ostatní výjimky označujeme jako kontrolované (checked),
protože překladač kontroluje dodržení pravidel:
● Každá metoda, která může vyhodit kontrolovanou výjimku,
se musí k této skutečnosti veřejně přihlásit
● Každé použití metody, která může vyhodit kontrolovanou výjimku,
musí být buď uzavřeno v bloku try…catch,
nebo se volající metoda musí přihlásit k tomu,
že může také vyhodit danou kontrolovanou výjimku
► Nekontrolované výjimky ohlašují chyby v programu,
kontrolované výjimky očekávatelné situace,
na jejichž výskyt má být program připraven
a měl by na ně umět reagovat
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
17
Hierarchie výjimek
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
18
Pořadí výjimek v blocích catch
► Třída NumberFormatException
je potomkem třídy RuntimeException
try {
Syntaktická chyba,
......
na druhý blok catch nikdy nedojde
}
catch (RuntimeException e) {
.........
}
Obrácené pořadí bloků catch
catch (NumberFormatException e){
vše vyřeší
........
try {
}
......
}
catch (NumberFormatException e) {
.........
}
catch (RuntimeException e){
........
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
19
Metody generující výjimky
► Java vyžaduje, aby programy, které používají metody
schopné vyvolat kontrolované výjimky,
byly o této schopnosti používaných metod informovány =>
pak vědí, které výjimku musí umět zachytit a ošetřit
► Všechny kontrolované výjimky, které může metoda vyhodit,
musí deklarovat v hlavičce za klíčovým slovem throws
► Deklarace vyhazování nekontrolovaných výjimek není povinná
public void metoda()
throws KontrolovanáVýjimka1,
KontrolovanáVýjimka2
{
// Tělo metody
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
20
Metody třídy Throwable
► String getMessage()
Vrátí zprávu popisující danou výjimku
► String toString()
Vrátí název třídy výjimky následovaný případnou zprávou
► void printStackTrace()
Vytiskne toString() následovaný sadou informací o volající
posloupnosti, která vedla k vzniku výjimky
► Throwable fillInStackTrace()
Připraví nové informace o volací posloupnosti
vedoucí k místu zavolání této metody
► StackTraceElement[] getStackTrace()
Vrátí uchované informace o volací posloupnosti dané výjimky
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
21
Zřetězené výjimky
► V některých situacích je vhodné v rámci ošetření výjimky vyvolat
jinou výjimku, a přitom umožnit zjistit,
která výjimka byla prvotním hybatelem celé akce
► Řada výjimek má mezi svými konstruktory i takové,
které akceptují jako poslední parametr
odkaz na výjimku, jež byla příčinou vyvolání dané výjimky
► Chce-li se program zeptat výjimky na výjimku, která ji způsobila,
použije metodu
public Throwable getCause()
► Ve zprávě o vyvolání výjimky jsou místa, kde byla jedna výjimka
nahrazena jinou, označována textem caused by:
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
22
Ukázka výpisu při zřetězení výjimek
HighLevelException: MidLevelException: LowLevelException
at Junk.a(Junk.java:13)
at Junk.main(Junk.java:4)
Caused by: MidLevelException: LowLevelException
at Junk.c(Junk.java:23)
at Junk.b(Junk.java:17)
at Junk.a(Junk.java:11)
... 1 more
Caused by: LowLevelException
at Junk.e(Junk.java:30)
at Junk.d(Junk.java:27)
at Junk.c(Junk.java:21)
... 3 more
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
23
Převod kontrolovaných na nekontrolované
► Ošetřování kontrolovaných výjimek obtěžuje
► Víme-li, že k dané výjimce nejspíš nedojde
a ošetřujeme-li ji pouze proto, že na tom překladač trvá,
můžeme pro případ, že by k výjimce přece jenom došlo
zaměnit kontrolovanou výjimku za nekontrolovanou
public void prevod( String s ) {
try {
prověř( s );
} catch( Exception ex ) {
throw new RuntimeException( " Neprověřeno! ", ex );
}
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
24
Vaše jistota na trhu IT
Definice vlastních výjimek
►Hierarchie výjimek
►Pořadí výjimek v blocích catch
►Metody generující výjimky
►Metody třídy Throwable
►Vlastní výjimky
►Zásady správného používání výjimek
Definice vlastních výjimek
► Výjimky jsou zcela běžné třídy;
považujeme-li to proto za vhodné, můžeme definovat i vlastní
► Před definicí nové výjimky bychom si měli ujasnit,
bude-li kontrolovaná či nekontrolovaná;
podle toho definujeme jejího předka
► Název výjimek končí dle konvencí slovem Exception
před nímž je naznačena podstata dané výjimky
● IllegalArgumetnException
● NoSuchMethodException
● BadStringOperationException
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
26
Příklad vlastní kontrolované výjimky
public class VelkýPrůšvihException
extends Exception
{
public VelkýPrůšvihException() {};
public VelkýPrůšvihException( String zpráva ) {
super( zpráva );
}
public VelkýPrůšvihException(String zpráva,
Throwable původce ) {
super( zpráva, původce );
}
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
27
Test správného vyhození výjimky
► Na vytvářených programech je třeba otestovat i to,
že v definovaných situacích vyhodí požadovanou výjimku
public void testVyhozeníVýjimky()
{
try {
metodaKteráMáVyhoditVýjimku();
} catch ( VelkýPrůšvihException vpe ) {
return;
}
fail( "Nebyla vyhozena výjimka VelkýPrůšvihException" );
}
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
28
Zásady správného používání výjimek
1/2
Neignorujte
výjimky
try {
//Nějaký kód
}
catch(Exception e){}
► Výjimky, o nichž víte, že nemohou nastat,
převeďte na nekontrolované pro případ,
že by v budoucích verzích programu nastat mohly
► Při ošetřování výjimek, které nastat mohou,
ale nemají vliv na chod programu,
vložte do těla ošetření alespoň vysvětlující komentář
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
29
Zásady správného používání výjimek
2/2
► Používejte výjimky pouze k ošetření výjimečných stavů
► Kontrolované výjimky používejte u stavů, z nichž se lze zotavit,
jinak použijte výjimky nekontrolované
► Vyhýbejte se zbytečnému používání kontrolovaných výjimek
● Programátory ošetřování kontrolovaných výjimek obtěžuje
a mají pak tendenci je ošetřovat prázdným blokem catch
► Dávejte přednost standardním výjimkám,
vyvolávejte výjimky odpovídající dané abstrakci
● Programátoři by měli z názvu výjimky poznat, co se stalo
● Standardní výjimky mají všeobecně známý význam
► Snažte se o atomičnost selhání; i po vyhození výjimky
by měl být objekt v dobře definovaném stavu
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
30
Zásady správného používání výjimek
3/2
► Doplňujte výjimky zprávami,
výjimka by sama měla poskytnout dostatek informací
a neměla by programátora nutit k podrobnější analýze programu
► Dokumentujte vyvolávané výjimky v dokumentačních
komentářích pomocí značky @throws
► Nedělejte bloky try zbytečně velké,
kód uvnitř těchto bloků se neoptimalizuje
► Umíte-li výjimku v metodě ošetřit, udělejte to
► Detekuje-li se chyba v jedné metodě a má se ošetřit v jiné
(stejné či jiné instance), použijte výjimku.
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
31
Nejčastěji používané výjimky
1/2
► IllegalArgumentException
Byla zadána nepovolená hodnota parametru
● Např. chci nastavit zápornou velikost grafického tvaru
► IllegalStateException
V daném stavu objektu nelze metodu provést
● Např. otevřu soubor, přečtu pár vět, zavřu soubor a chci znovu přečíst větu
► NullPointerException
Byla vyvolána metoda instance, na níž ukazuje prázdný odkaz,
nebo byl předán nepovolený prázdný odkaz v parametru
► ArrayIndexOutOfBoundException
Byly zadány špatné meze pole, buď záporné nebo moc velké
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
32
Nejčastěji používané výjimky
2/2
► ConcurrentModificationException
V průběhu iterace byla změněna struktura kontejneru
● Např. byl do kontejneru přidán prvek
► NumberFormatException
Je požadován špatný převod řetězce na číslo či naopak
● Chci-li např. převést na číslo řetězec, který není číslem
● Častá chyba v metodách String.format či PrintStream.printf
► ClassCastException
Požadované přetypování není možné
► UnsupportedOperationException
Požadovaná operace není podporována
(např. chci přidat prvek do neměnného kontejneru)
Copyright © 2006, Rudolf Pecinovský
VŠE – 05
33
Vaše jistota na trhu IT
Děkuji za pozornost
►Rudolf Pecinovský
http://vyuka.pecinovsky.cz/vse
mail: [email protected]
ICQ: 158 156 600