Výjimkou Java jsou typy knihoven a jazykové funkce používané k reprezentaci a řešení selhání programu. Pokud jste chtěli pochopit, jak je selhání znázorněno ve zdrojovém kódu, jste na správném místě. Kromě přehledu výjimek Java vám představím jazykové funkce jazyka Java pro házení objektů, zkoušení kódu, který může selhat, chytání hozených objektů a vyčištění kódu Java po vyvolání výjimky.
V první polovině tohoto kurzu se dozvíte o základních jazykových funkcích a typech knihoven, které existují od verze Java 1.0. Ve druhé polovině objevíte pokročilé funkce představené v novějších verzích Java.
Všimněte si, že příklady kódu v tomto kurzu jsou kompatibilní s JDK 12.
stáhnout Získat kód Stáhněte si zdrojový kód například pro aplikace v tomto výukovém programu. Vytvořil Jeff Friesen pro JavaWorld.Co jsou výjimky Java?
Selhání nastane, když je normální chování Java programu přerušeno neočekávaným chováním. Tato divergence je známá jako výjimka. Program se například pokusí otevřít soubor a přečíst jeho obsah, ale soubor neexistuje. Java klasifikuje výjimky do několika typů, takže zvažte každou z nich.
Zkontrolované výjimky
Java klasifikuje výjimky vyplývající z externích faktorů (například chybějící soubor) jako kontrolované výjimky. Kompilátor Java kontroluje, zda jsou takové výjimky zacházeno (opraveno) tam, kde se vyskytují nebo je dokumentováno, že mají být zpracovány jinde.
Obslužné rutiny výjimek
An obsluha výjimek je sekvence kódu, který zpracovává výjimku. Dotazuje se na kontext - to znamená, že čte hodnoty uložené z proměnných, které byly v rozsahu v době, kdy došlo k výjimce - a poté použije to, co se naučí, k obnovení normálního chování programu Java. Například obslužná rutina výjimky může číst uložený název souboru a vyzvat uživatele k nahrazení chybějícího souboru.
Runtime (nezaškrtnuté) výjimky
Předpokládejme, že se program pokusí rozdělit celé číslo na celé číslo 0. Tato nemožnost ilustruje další druh výjimky, jmenovitě a runtime výjimka. Na rozdíl od kontrolovaných výjimek, runtime výjimky obvykle vznikají ze špatně napsaného zdrojového kódu, a proto by je měl opravit programátor. Protože kompilátor nekontroluje, zda jsou výjimky za běhu zpracovány nebo zdokumentovány, aby byly zpracovány jinde, můžete si myslet na výjimku za běhu jako nezaškrtnutá výjimka.
O výjimkách za běhu
Můžete upravit program tak, aby zpracoval runtime výjimku, ale je lepší opravit zdrojový kód. Výjimky za běhu často vznikají z předávání neplatných argumentů metodám knihovny; buggy volací kód by měl být opraven.
Chyby
Některé výjimky jsou velmi závažné, protože ohrožují schopnost programu pokračovat v provádění. Například program se pokusí přidělit paměť z JVM, ale není dostatek volné paměti k uspokojení požadavku. Další vážná situace nastane, když se program pokusí načíst soubor třídy přes a Class.forName ()
volání metody, ale soubor třídy je poškozen. Tento druh výjimky se označuje jako chyba. Nikdy byste se neměli pokoušet vypořádat se s chybami sami, protože JVM by se z nich nemohl vzpamatovat.
Výjimky ve zdrojovém kódu
Výjimku lze ve zdrojovém kódu představit jako chybový kód nebo jako objekt. Představím obojí a ukážu vám, proč jsou objekty lepší.
Chybové kódy versus objekty
Programovací jazyky jako C používají celočíselné chybové kódy představovat selhání a důvody selhání - tj. výjimky. Zde je několik příkladů:
if (chdir ("C: \ temp")) printf ("Nelze změnit na dočasný adresář:% d \ n", errno); SOUBOR * fp = fopen ("C: \ temp \ foo"); if (fp == NULL) printf ("Nelze otevřít foo:% d \ n", errno);
C chdir ()
Funkce (změnit adresář) vrací celé číslo: 0 při úspěchu nebo -1 při selhání. Podobně C fopen ()
Funkce (file open) vrací nenulovou hodnotu ukazatel (celočíselná adresa) na a SOUBOR
struktura na úspěch nebo nulový (0) ukazatel (reprezentovaný konstantou NULA
) při selhání. V obou případech, abyste identifikovali výjimku, která způsobila selhání, musíte přečíst globální errno
celočíselný chybový kód proměnné.
Chybové kódy představují určité problémy:
- Celá čísla nemají smysl; nepopisují výjimky, které představují. Co například znamená 6?
- Přiřazení kontextu k chybovému kódu je nepříjemné. Můžete například chtít načíst název souboru, který nelze otevřít, ale kam chcete uložit název souboru?
- Celá čísla jsou libovolná, což může vést ke zmatku při čtení zdrojového kódu. Například zadání
if (! chdir ("C: \ temp"))
(!
znamená NE) namístoif (chdir ("C: \ temp"))
testovat selhání je jasnější. Pro označení úspěchu však byla zvolena 0 atdif (chdir ("C: \ temp"))
musí být specifikováno pro testování selhání. - Chybové kódy je příliš snadné ignorovat, což může vést k chybovému kódu. Například může programátor určit
chdir ("C: \ temp");
a ignorovatif (fp == NULL)
šek. Programátor navíc nemusí zkoumaterrno
. Při netestování selhání se program chová nestandardně, když některá funkce vrací indikátor selhání.
K vyřešení těchto problémů přijala Java nový přístup ke zpracování výjimek. V Javě kombinujeme objekty, které popisují výjimky, s mechanismem založeným na házení a chytání těchto objektů. Zde jsou některé výhody použití objektů oproti chybovému kódu k označení výjimek:
- Objekt lze vytvořit ze třídy se smysluplným názvem. Například,
FileNotFoundException
(vjava.io
balíček) je smysluplnější než 6. - Objekty mohou ukládat kontext do různých polí. V polích objektu můžete například uložit zprávu, název souboru, který nelze otevřít, nejnovější pozici, kde operace analýzy selhala, a / nebo další položky.
- Nepoužíváte
-li
prohlášení k testování selhání. Místo toho jsou objekty výjimky vyvolány obslužné rutině, která je oddělená od kódu programu. Výsledkem je, že zdrojový kód je čitelnější a méně pravděpodobné, že bude chybný.
Vrhací a jeho podtřídy
Java poskytuje hierarchii tříd, které představují různé druhy výjimek. Tyto třídy jsou zakořeněny v java.lang
balíček Vrhací
třídy, spolu s jeho Výjimka
, RuntimeException
, a Chyba
podtřídy.
Vrhací
je nejvyšší nadtřída, pokud jde o výjimky. Pouze objekty vytvořené z Vrhací
a jeho podtřídy mohou být hozeny (a následně chyceny). Takové objekty jsou známé jako házené předměty.
A Vrhací
objekt je spojen s a podrobná zpráva který popisuje výjimku. K vytvoření a je poskytnuto několik konstruktorů, včetně dvojice popsané níže Vrhací
objekt s podrobnou zprávou nebo bez ní:
- Vrhací () vytváří
Vrhací
bez podrobných zpráv. Tento konstruktor je vhodný pro situace, kde není žádný kontext. Například chcete jen vědět, že zásobník je prázdný nebo plný. - Throwable (String message) vytváří
Vrhací
szpráva
jako podrobná zpráva. Tuto zprávu lze odeslat uživateli nebo přihlásit.
Vrhací
poskytuje Řetězec getMessage ()
metoda pro vrácení podrobné zprávy. Poskytuje také další užitečné metody, které uvedu později.
Třída výjimek
Vrhací
má dvě přímé podtřídy. Jedna z těchto podtříd je Výjimka
, který popisuje výjimku vyplývající z externího faktoru (například pokus o čtení z neexistujícího souboru). Výjimka
deklaruje stejné konstruktory (se stejnými seznamy parametrů) jako Vrhací
a každý konstruktor vyvolá své Vrhací
protějšek. Výjimka
dědí Vrhací
metody; deklaruje žádné nové metody.
Java poskytuje mnoho tříd výjimek, které přímo podtřídu Výjimka
. Tady jsou tři příklady:
- CloneNotSupportedException signalizuje pokus o klonování objektu, jehož třída neimplementuje
Cloneable
rozhraní. Oba typy jsou vjava.lang
balík. - IOException signalizuje, že došlo k nějakému selhání I / O. Tento typ se nachází v
java.io
balík. - ParseException signalizuje, že při analýze textu došlo k chybě. Tento typ naleznete v
java.text
balík.
Všimněte si, že každý Výjimka
název podtřídy končí slovem Výjimka
. Tato konvence usnadňuje identifikaci účelu třídy.
Obvykle budete podtřídy Výjimka
(nebo jedna z jejích podtříd) s vašimi vlastními třídami výjimek (jejichž jména by měla končit na Výjimka
). Zde je několik příkladů vlastních podtříd:
public class StackFullException extends Exception {} public class EmptyDirectoryException extends Exception {private String directoryName; public EmptyDirectoryException (String message, String directoryName) {super (zpráva); this.directoryName = adresář; } public String getDirectoryName () {návrat adresářeName; }}
První příklad popisuje třídu výjimek, která nevyžaduje podrobnou zprávu. Je to výchozí vyvolání konstruktoru noargument Výjimka()
, který vyvolá Vrhací ()
.
Druhý příklad popisuje třídu výjimky, jejíž konstruktor vyžaduje podrobnou zprávu a název prázdného adresáře. Konstruktor vyvolá Výjimka (řetězcová zpráva)
, který vyvolá Throwable (String message)
.
Objekty vytvořené z Výjimka
nebo jedna z jejích podtříd (kromě RuntimeException
nebo jedna z jejích podtříd) jsou zaškrtnuté výjimky.
RuntimeException Třída
Výjimka
je přímo podtřída RuntimeException
, který popisuje výjimku s největší pravděpodobností vyplývající ze špatně napsaného kódu. RuntimeException
deklaruje stejné konstruktory (se stejnými seznamy parametrů) jako Výjimka
a každý konstruktor vyvolá své Výjimka
protějšek. RuntimeException
dědí Vrhací
metody. Deklaruje žádné nové metody.
Java poskytuje mnoho tříd výjimek, které přímo podtřídu RuntimeException
. Následující příklady jsou všichni členové java.lang
balík:
- Aritmetická výjimka signalizuje neplatnou aritmetickou operaci, jako je pokus o dělení celého čísla číslem 0.
- IllegalArgumentException signalizuje, že metodě byl předán nezákonný nebo nevhodný argument.
- NullPointerException signalizuje pokus o vyvolání metody nebo o přístup k poli instance pomocí nulové reference.
Objekty vytvořené z RuntimeException
nebo jedna z jejích podtříd je nezaškrtnuté výjimky.
Třída Error
Vrhací
Další přímá podtřída je Chyba
, který popisuje závažný (i abnormální) problém, se kterým by se rozumná aplikace neměla snažit vypořádat - například nedostatek paměti, přetečení zásobníku JVM nebo pokus o načtení třídy, kterou nelze najít. Jako Výjimka
, Chyba
deklaruje identické konstruktory Vrhací
, dědí Vrhací
metody a nedeklaruje žádnou ze svých vlastních metod.
Můžete identifikovat Chyba
podtřídy z konvence, jejichž názvy tříd končí Chyba
. Mezi příklady patří OutOfMemoryError
, Chyba spojení
, a StackOverflowError
. Všechny tři typy patří do java.lang
balík.
Házení výjimek
Funkce knihovny C upozorní volající kód výjimky nastavením globálu errno
proměnnou na kód chyby a vrácení kódu chyby. Naproti tomu metoda Java hodí objekt. Vědět, jak a kdy vyvolávat výjimky, je základním aspektem efektivního programování v jazyce Java. Vyvolání výjimky zahrnuje dva základní kroky:
- Použijte
házet
příkaz k vyvolání objektu výjimky. - Použijte
hodí
klauzule informovat kompilátor.
Pozdější části se zaměří na zachycení výjimek a vyčištění po nich, ale nejprve se pojďme dozvědět více o hodu.
Prohlášení hodu
Java poskytuje házet
příkaz k vyvolání objektu, který popisuje výjimku. Tady je syntaxe házet
prohlášení :
házet házet;
Objekt identifikovaný pomocí házet
je instancí Vrhací
nebo některou z jejích podtříd. Obvykle však házíte pouze objekty vytvořené z podtříd třídy Výjimka
nebo RuntimeException
. Zde je několik příkladů:
hodit novou FileNotFoundException ("nelze najít soubor" + název souboru); házet novou IllegalArgumentException ("argument předaný do počtu je menší než nula");
Vrhací hod je vyvolán z aktuální metody do JVM, který kontroluje tuto metodu pro vhodnou obslužnou rutinu. Pokud není nalezen, JVM odvíjí zásobník volání metody a hledá nejbližší volací metodu, která dokáže zpracovat výjimku popsanou v hodu. Pokud najde tuto metodu, předá vyvolávací metodu obslužné rutině metody, jejíž kód je spuštěn pro zpracování výjimky. Pokud není nalezena žádná metoda pro zpracování výjimky, JVM končí vhodnou zprávou.
Klauzule hází
Je třeba informovat kompilátor, když vyhodíte kontrolovanou výjimku z metody. Udělejte to připojením a hodí
klauzule do záhlaví metody. Tato klauzule má následující syntaxi:
hodí checkedExceptionClassName (, checkedExceptionClassName)*
A hodí
klauzule se skládá z klíčového slova hodí
následuje čárkami oddělený seznam názvů tříd kontrolovaných výjimek vyhozených z metody. Zde je příklad:
public static void main (String [] args) hodí ClassNotFoundException {if (args.length! = 1) {System.err.println ("usage: java ... classfile"); vrátit se; } Class.forName (args [0]); }
Tento příklad se pokusí načíst soubor třídy identifikovaný argumentem příkazového řádku. Li Class.forName ()
nemůže najít třídní soubor, hodí a java.lang.ClassNotFoundException
objekt, což je zaškrtnutá výjimka.
Zkontrolovaná kontroverze výjimek
The hodí
klauzule a kontrolované výjimky jsou kontroverzní. Mnoho vývojářů nenávidí, když jsou nuceni specifikovat hodí
nebo zpracovat zaškrtnuté výjimky. Další informace o tom z mého Jsou kontrolované výjimky dobré nebo špatné? příspěvek na blogu.