Naučte se Javu – výjimky

31. července 2002

Pomocí mechanismu výjimek můžeme lépe reagovat na chybové a nestandardní stavy běhu programu. Místo toho, abyste po každém vykonaném příkazu kontrolovali chyby, které mohou nastat, umístíte ošetření chyb celého bloku kódu na jedno místo. Ukáži vám, jak se s výjimkami pracuje a jak je používat.

Objekty výjimek

Výjimky v Javě jsou objekty, které jsou potomky objektu java.lang.Throwable. Tato třída má dvě podtřídy java.lang.Error a java.lang.Exception (pro obě se používá společný název výjimky). Pokud v programu dojde k výjimečnému stavu, vznikne objekt výjimky a program může na tuto výjimku reagovat, odchytit ji.

Třída java.lang.Error a její podtřídy obvykle představují vážné chyby při běhu, ze kterých se program nemůže zotavit, například nedostatek paměti či chyby virtuálního stroje. Tyto výjimky by aplikace neměla odchytávat a měly by vést ke skončení programu.

Třída java.lang.Exception a její podtřídy představují výjimky, ze kterých se lze zotavit a program by je měl odchytávat a ošetřovat. Například java.io.IOException indikuje chybu při vstupně-výstupních operacích nebo java.io.EOFException indikuje čtení za koncem souboru.

Ošetření výjimek

Výjimky se ošetřují pomocí konstrukce try-catch-finally. Blok za klíčovým slovem try obsahuje nebezpečný kód, ve kterém může dojít k výjimce. Za ním následuje žádný nebo více bloků catch, ve kterých jsou ošetřeny jednotlivé typy výjimek, které mohou nastat v bloku try. Nepovinný blok finally obsahuje kód, který je vždy spuštěn nezávisle na tom, jak dopadl blok try (zda proběhl bezchybně či skončil výjimkou).

try {
   // nebezpečný blok kódu, v němž mohou nastat výjimky
}
catch (NejakaVyjimka1 nv1) {
   // zde se ošetří výjimky typu NejakaVyjimka1
   // a jeho podtypu
}
catch (NejakaVyjimka2 nv2) {
   // zde se ošetří výjimky typu NejakaVyjimka2
   // a jeho podtypu
}
finally {
   // tento kód se provede vždy po opuštění klausule try
}

Postup zpracování

Při vstupu do bloku try se příkazy vykonávají v pořadí, ve kterým jsou zapsány. Pokud vše proběhne bezchybně, je po bloku try spuštěn případný blok finally. Pokud v průběhu bloku try nastane výjimka, přeruší se jeho vykonávání. Pokud některá klausule catch ošetřuje daný typ výjimky, spustí se blok kódu první takové. Nakonec se spustí blok finally, pokud je přítomen.

Za klíčovým slovem catch následuje v kulatých závorkách typ výjimky a jméno proměnné, která na ni bude odkazovat. Tato klausule odchytává pouze výjimky tohoto typu a jeho podtypů. Proměnná odkazující na výjimku je platná pouze v daném bloku catch.

Pokud výjimku neodchytí blok, který ji vyhodil, výjimka se šíří k následujícímu ohraničujícímu bloku. Pokud se nedochytí ani v něm, propaguje se dále. Pokud se neodchytí nikde v metodě, šíří se do nadřazené metody (která tuto metodu vyvolala) a dále po struktuře volání metod směrem ven. Pokud výjimku neodchytí nikdo, dostane se až do metody main(), kde způsobí ukončení interpretu Javy.

Metody výjimek

V objektu java.lang.Throwable je definováno několik užitečných metod. Metoda getMessge() poskytuje krátkou zprávu čitelnou pro člověka (může být však rovna null). Metoda toString() vrátí název třídy dané výjimky a zprávu (výstup getMessage()). Metoda printStackTrace() vypíše (na chybový výstup) výstup metody toString(), dále pak zásobník volání metod aktuální v době chyby s názvy tříd, metod a čísly řádků, kde k chybě došlo. Výstup může vypadat například takto:

java.lang.NullPointerException
   at MojeTrida.treti(MojeTrida.java:9)
   at MojeTrida.druha(MojeTrida.java:6)
   at MojeTrida.první(MojeTrida.java:3)

Výstup by odpovídal tomuto objektu:

class MojeTrida {
   public static void prvni() {
      druha(null);
   }
   static void druha(int[] a) {
      treti(a);
   }
   static void treti(int[] b) {
      System.out.println(b[0]);
   }
}

Deklarace výjimek

Je nutné, aby každá metoda, která může způsobit výjimku, ji buď odchytila nebo specifikovala, že tuto výjimku způsobuje. Používá se k tomu klíčové slovo throws v deklaraci metody:

public void nactiSoubor() throws IOException {
   // kód, který může způsobit výjimku typu java.io.IOException
   // (nebo jejího podtypu), ale tuto výjimku neodchytává
}

Není nutné ošetřovat ani deklarovat výjimky (pod)typu java.lang.Error ani java.lang.RuntimeException, protože je může potenciálně vyvolat každá metoda a měly by vést k přerušení programu.

Vlastní výjimky

Pomocí klíčového slova throw můžeme vyvolávat také své vlastní výjimky (nebo standardní výjimky). Vlastní výjimku definujeme jako objekt dědící od objektu java.lang.Throwable nebo nějakého jeho podobjektu:

public class MojeVyjimka extends java.lang.Exception {
   public MojeVyjimka() {
      super();
   }
   public MojeVyjimka(String a) {
      super(a);
   }
}
throw new MojeVyjimka(„Nastala MojeVyjimka“);
   // parametr konstruktoru
   // se stane zprávou, kterou lze získat metodou getMessage()

Pokud vyhodíte vlastní výjimku, zpracovává se stejným mechanismem jako standardní výjimky (konstrukcemi try-catch-finally a propagací po struktuře kódu).

S výjimkami se budeme často setkávat v následujících článcích, kdy budeme mluvit o práci se vstupy a výstupy a o síťové komunikaci. Hned v příštím článku se k výjimkám ještě vrátíme, uvedeme si seznam těch nejčastěji používaných výjimek s krátkým popisem.

Starší komentáře ke článku

Pokud máte zájem o starší komentáře k tomuto článku, naleznete je zde.

Štítky: Články

Mohlo by vás také zajímat

Nejnovější

Napsat komentář

Vaše e-mailová adresa nebude zveřejněna. Vyžadované informace jsou označeny *