Java a výjimky – úvod do problematiky výjimek
Tento článek si klade za cíl seznámit čtenáře s principem fungování mechanismu výjimek v prostředí platformy Java. Ukážeme si používání konstrukcí try, catch a finally, základní rozdělení výjimek a jejich objektovou hierarchii.
Výjimku chápeme v kontextu Javy jako důsledek výjimečné, neočekávané či chybové události v rámci vykonávání programu. Je trochu zavádějící uvažovat o výjimkách pouze v intencích chyb. Mechanismus výjimek pokrývá daleko širší prostor. V případě vzniku výjimky bychom měli chování kódu podřídit třem základním faktorům:
- úspěšně zpracovat vlastní výjimku
- umožnit zpětné dohledání a analýzu výjimky
- podat srozumitelnou informaci o výjimce navenek systému
Zpracování vlastní výjimky je proces, kdy se v kódu rozhodujeme, jak s výjimkou naložit. Aniž bychom nyní zabíhali do rozdělení výjimek, ke kterému se dostaneme v další části článku, prozradíme si, že výjimku můžeme ošetřit a nebo ji postoupit výše. Pokud máme v kontextu zachycení výjimky dost informací na její zpracování, měli bychom tak učinit.
Zpětné dohledání výjimky nastává v případech, kdy analyzujeme vznik výjimky, například při selhání systému nebo jeho neočekávaném chování. Činnost zpětného dohledání výjimky klade důraz na zaznamenání vlastní výjimky a poskytnutí maximálního počtu indicií, ze kterých je možné odvodit vznik výjimky. Zaznamenání výjimky spadá na úroveň aplikačního logu.
Podáním srozumitelné informace se rozumí takové chování, kdy klient systému porozumí důvodu vzniku výjimky. Pokud předaná informace vyvolaná vznikem výjimky inklinuje k variaci na téma zprávy Chyba:DataFormatException
, dosáhnete spíše uživatelova zmatení než srozumitelného vysvětlení, že bylo zadáno datum v nesprávném formátu. Podání srozumitelné informace má více aspektů, například lokalizace chybové zprávy, vlastní forma zprávy (klient nemusí být uživatel, ale jiný systém) a podobně.
Try, catch, finally konstrukce a příkazy throw a throws
Před rozdělením výjimek si zopakujeme základní příkazy a konstrukce pro práci s výjimkami.
Chráněný blok, ošetření výjimky a finally
Chráněný blok je uvozen příkazem try
a uzavřen mezi složené závorky. Jakoukoli výjimku vzniklou v chráněném bloku je možné ošetřit. K ošetření se používá příkaz catch
, za nímž následuje konkrétní datový typ výjimky, kterou bude tento blok zpracovávat. Blok ošetření je opět omezen složenými závorkami.
try{
//chráněný blok
}catch(Datovy typ výjimky){
//ošetření výjimky
}
K chráněnému bloku patří i blok finally
. Pokud vznikne v chráněném bloku výjimka, běh programu pokračuje nejdříve přes nejbližší blok catch
, který ošetřuje výjimku daného datového typu, a poté přes blok finally
(pokud je deklarován). Pokud výjimka nevznikne, běh programu pokračuje po posledním příkazu chráněného bloku opět přes blok finally
. Blok finally
se proto využívá pro operace, které musí být provedeny bez ohledu na fakt, jestli k výjimce dojde či nikoli – velmi často jde o uvolnění zdrojů (databázové připojení, soubor) alokovaných v rámci chráněného bloku.
try{
//chráněný blok
}catch(Datovy typ výjimky){
//ošetření výjimky
}finally{
//kód, provedený bez ohledu na vznik výjimky
}
Je potřeba si uvědomit, že blok finally
lze využít i bez bloku catch
.
try{
//chráněný blok
}finally{
//kód, provedený bez ohledu na vznik výjimky
}
K výjimkám nerozlučně patří i příkazy throw
a throws
. Příkaz throw
se používá k vyhození výjimky. V podstatě existují dva způsoby – buď konstruktorem vytvoříme novou výjimku a tu pomocí throw
vyhodíme (throw new MyException();
), nebo instanci výjimky již máme (například zachycením v bloku catch
) a příkazem throw
ji znovu vyhodíme.
Příkaz throws
se zapisuje v signatuře metody a tvoří součást API public String doSomething() throws MyException()
. Za throws
následuje výčet datových typů výjimek, které může metoda vyhazovat. Jakoukoli výjimku deklarovanou v signatuře není programátor nucen uvnitř metody ošetřovat. Naopak throws
lze z hlediska klienta API považovat za zřeknutí se výjimky.
Základní rozdělení výjimek
Už víme, co je to výjimka a jak bychom na ni měli nahlížet. Nyní nastal čas seznámení s rozdělením výjimek. Java podporuje dva základní typy výjimek z hlediska jejich správy:
- výjimky kontrolované, takzvané checked exception
- výjimky nekontrolované, takzvané běhové či runtime exception
Kontrolované výjimky
Kontrolované výjimky jsou charakteristické tím, že klientský kód je nucen tyto výjimky ošetřit (catch
blok) anebo propagovat (throws
). Kontrola, jestli se tak děje, je provedena staticky, tedy v době kompilace kódu. Standardní API Javy deklaruje několik desítek kontrolovaných výjimek, které mohou nastat při práci s tou či onou částí API. Podívejme se například na ošetření a propagace výjimky vzniklé při práci se souborem.
Ošetření kontrolované výjimky
public void configure(final String confFileName){
Properties props;
try{
File confFile = new File(confFileName);
FileInputStream fis = new FileInputStream(confFile);
props = new Properties();
props.load(fis);
}catch(FileNotFoundException fnf){
//použijeme defaultní konfiguraci
props = defaultProps;
}
…
…
…
}
Propagování kontrolované výjimky
public void configure(final String confFileName) throws FileNotFoundException{
File confFile = new File(confFileName)
FileInputStream fis = new FileInputStream(confFile);
Properties props = new Properties();
…
…
…
}
Nekontrolované výjimky
Nekontrolované či běhové výjimky se od kontrolovaných odlišují v tom, že programátor není explicitně nucen k jejich ošetření či propagaci. Nekontrolované výjimky vznikají za běhu systému, a proto nemá cenu jejich výskyt predikovat a snažit se je ošetřit nebo je propagovat. Mezi tyto výjimky patří například práce mimo rozsah pole ArrayIndexOutOfBoundsException
, práce na null referenci NullPointerException
a podobně.
Objektová hierarchie výjimek
Kořenovou třídou pro všechny výjimky a chyby představuje Throwable
. Standardní API Javy definuje dva potomky, Error
a Exception
. Třída Error
a její potomci představují rodinu závažných chyb, jedná se o chyby nekontrolované (běhové) a jejich chytání nebo převod na kontrolované nemá smysl.
Do kategorie závažných chyb spadají například chyby vzniklé při běhu JVM (Java Virtual Machine), jako je nedostatek paměti, přetečení zásobníku nebo vnitřní chyba JVM. Třída Exception
představuje základní třídu (předka) pro všechny výjimky. Od této třídy jsou přímo odvozeny všechny kontrolované výjimky. Nekontrolované výjimky jsou odvozeny od RuntimeException
. Základní hierarchii znázorňuje následující model tříd:
Takto nastavená hierarchie se využívá při tvorbě odvozených výjimek, které z těchto základních vycházejí. Výjimky mají ještě jednu základní vlastnost, umožňují řetězení, takzvaný exception chaining. Příklad odvozené kontrolované i nekontrolované výjimky najdete v přiložených zdrojových kódech.
Starší komentáře ke článku
Pokud máte zájem o starší komentáře k tomuto článku, naleznete je zde.
Mohlo by vás také zajímat
-
Monitory OLED: klíčové pojmy a funkce
13. května 2024 -
Jak se chránit před podvody na internetu – část 2
14. října 2024 -
Souboj na trhu s CPU pro servery: AMD vs. Intel
8. prosince 2023
Nejnovější
-
Windows App: Pracujte odkudkoliv, kdykoliv
3. listopadu 2024 -
Od iPhonu po Android: Ultra HDR přináší nový standard fotografií
1. listopadu 2024 -
AI a internetové podvody
29. října 2024 -
Užitečné nástroje pro bezpečnost na internetu
17. října 2024