Výnimkou Java sú typy knižníc a jazykové funkcie používané na zastupovanie a riešenie zlyhaní programu. Ak ste chceli pochopiť, ako je zlyhanie vyjadrené v zdrojovom kóde, ste na správnom mieste. Okrem prehľadu výnimiek jazyka Java vám pomôžeme s jazykovými funkciami jazyka Java na vyhadzovanie objektov, skúšanie kódu, ktorý môže zlyhať, chytanie vyhodených objektov a čistenie kódu Java po vyvolaní výnimky.
V prvej polovici tohto tutoriálu sa dozviete o základných jazykových vlastnostiach a typoch knižníc, ktoré existujú od verzie Java 1.0. V druhej polovici objavíte pokročilé funkcie zavedené v novších verziách Java.
Upozorňujeme, že príklady kódov v tomto tutoriále sú kompatibilné s JDK 12.
stiahnuť Získajte kód Stiahnite si zdrojový kód napríklad pre aplikácie v tejto príručke. Vytvoril Jeff Friesen pre JavaWorld.Čo sú výnimky Java?
Zlyhanie nastane, keď je normálne správanie programu Java prerušené neočakávaným správaním. Táto odchýlka je známa ako výnimkou. Napríklad sa program pokúsi otvoriť súbor, aby prečítal jeho obsah, ale súbor neexistuje. Java klasifikuje výnimky do niekoľkých typov, zvážme teda každú z nich.
Skontrolované výnimky
Java klasifikuje výnimky vyplývajúce z externých faktorov (napríklad chýbajúci súbor) ako skontrolované výnimky. Kompilátor Java kontroluje, či sú tieto výnimky buď vybavil (opravené) tam, kde sa vyskytujú alebo je zdokumentované, že sa s nimi zaobchádza inde.
Obsluha výnimiek
An obsluha výnimky je sekvencia kódu, ktorá spracováva výnimku. Dotýka sa kontextu - to znamená, že číta hodnoty uložené z premenných, ktoré boli v rozsahu v čase, keď došlo k výnimke - a potom použije to, čo sa naučí, na obnovenie behu programu Java. Obslužný program výnimiek môže napríklad prečítať uložený názov súboru a vyzvať používateľa, aby nahradil chýbajúci súbor.
Výnimky za behu (neoznačené)
Predpokladajme, že sa program pokúsi rozdeliť celé číslo na celé číslo 0. Táto nemožnosť ilustruje iný druh výnimky, a to a runtime výnimka. Na rozdiel od kontrolovaných výnimiek, runtime výnimky zvyčajne vychádzajú zo zle napísaného zdrojového kódu, a mal by ich preto opraviť programátor. Pretože kompilátor nekontroluje, či sú runtime výnimky spracované alebo zdokumentované tak, aby boli spracované inde, môžete si runtime výnimku predstaviť ako nekontrolovaná výnimka.
O výnimkách za behu
Program môžete upraviť tak, aby spracovával výnimku za behu, ale je lepšie opraviť zdrojový kód. Výnimky za behu často vznikajú pri odovzdávaní neplatných argumentov metódam knižnice; buggy volací kód by mal byť opravený.
Chyby
Niektoré výnimky sú veľmi vážne, pretože ohrozujú schopnosť programu pokračovať v jeho spustení. Napríklad program sa pokúša prideliť pamäť z JVM, ale nie je dostatok voľnej pamäte na uspokojenie požiadavky. Ďalšia vážna situácia nastane, keď sa program pokúsi načítať triedny súbor pomocou a Class.forName ()
volanie metódy, ale triedny súbor je poškodený. Tento druh výnimky je známy ako chyba. Nikdy by ste sa nemali pokúšať chyby spracovávať sami, pretože JVM sa z nich nemusí vedieť spamätať.
Výnimky v zdrojovom kóde
Výnimku možno v zdrojovom kóde predstavovať ako kód chyby alebo ako objekt. Predstavím oboje a ukážem vám, prečo sú predmety lepšie.
Chybové kódy verzus objekty
Programovacie jazyky ako C používajú celočíselné chybové kódy predstavovať zlyhanie a dôvody zlyhania - teda výnimky. Tu je niekoľko príkladov:
if (chdir ("C: \ temp")) printf ("Nemožno zmeniť dočasný adresár:% d \ n", errno); SÚBOR * fp = fopen ("C: \ temp \ foo"); if (fp == NULL) printf ("Nie je možné otvoriť foo:% d \ n", errno);
C chdir ()
(zmena adresára) funkcia vráti celé číslo: 0 pri úspechu alebo -1 pri zlyhaní. Podobne aj C fopen ()
(otvorený súbor) vráti nenulovú hodnotu ukazovateľ (celočíselná adresa) na a SÚBOR
štruktúra na úspech alebo nulový (0) ukazovateľ (predstavovaný konštantou NULOVÝ
) pri zlyhaní. V obidvoch prípadoch si musíte prečítať globálnu, aby ste identifikovali výnimku, ktorá zlyhanie spôsobila errno
celočíselný chybový kód premennej.
Chybové kódy spôsobujú určité problémy:
- Celé čísla sú nezmyselné; neopisujú výnimky, ktoré zastupujú. Čo napríklad znamená 6?
- Priraďovanie kontextu k chybovému kódu je nepríjemné. Napríklad budete chcieť vytlačiť názov súboru, ktorý sa nepodarilo otvoriť, ale kam chcete uložiť názov súboru?
- Celé čísla sú ľubovoľné, čo môže pri čítaní zdrojového kódu viesť k zámene. Napríklad upresnenie
if (! chdir ("C: \ temp"))
(!
znamená NIE) namiestoif (chdir ("C: \ temp"))
testovanie zlyhania je jasnejšie. Avšak 0 bola vybraná na označenie úspechu atďif (chdir ("C: \ temp"))
musí byť špecifikované na testovanie poruchy. - Chybové kódy je príliš ľahké ignorovať, čo môže viesť k chybovému kódu. Môže napríklad určiť programátor
chdir ("C: \ temp");
a ignorovaťif (fp == NULL)
skontrolovať. Ďalej nemusí programátor skúmaťerrno
. Testovaním chyby sa program chová nestabilne, keď niektorá z funkcií vráti indikátor zlyhania.
Na vyriešenie týchto problémov Java prijala nový prístup k spracovaniu výnimiek. V Jave kombinujeme objekty, ktoré popisujú výnimky, s mechanizmom založeným na hádzaní a chytaní týchto objektov. Tu sú niektoré výhody použitia objektov oproti chybovému kódu na označenie výnimiek:
- Objekt je možné vytvoriť z triedy so zmysluplným názvom. Napríklad,
FileNotFoundException
(vjava.io
balíček) je zmysluplnejšia ako 6. - Objekty môžu ukladať kontext do rôznych polí. Do polí objektu môžete napríklad uložiť správu, názov súboru, ktorý sa nedal otvoriť, najnovšiu pozíciu, kde zlyhala operácia syntaktickej analýzy, alebo ďalšie položky.
- Nepoužívate
ak
vyhlásenia na testovanie zlyhania. Namiesto toho sa objekty výnimky vrhnú na obslužnú rutinu, ktorá je oddelená od programového kódu. Vďaka tomu je zdrojový kód ľahšie čitateľný a je menej pravdepodobné, že bude chybný.
Hádzateľná a jej podtriedy
Java poskytuje hierarchiu tried, ktoré predstavujú rôzne druhy výnimiek. Tieto triedy majú korene v java.lang
balíček Hoditeľné
triedy, spolu s jej Výnimka
, RuntimeException
a Chyba
podtriedy.
Hoditeľné
je najvyššia nadtrieda, pokiaľ ide o výnimky. Iba objekty vytvorené z Hoditeľné
a jeho podtriedy môžu byť vyhodené (a následne chytené). Takéto objekty sú známe ako hádzacie predmety.
A Hoditeľné
objekt je spojený s a podrobná správa ktorý popisuje výnimku. Na vytvorenie a. Je poskytnutých niekoľko konštruktorov, vrátane dvojice popísanej nižšie Hoditeľné
objekt s podrobnou správou alebo bez nej:
- Hádzateľné () vytvára a
Hoditeľné
bez podrobnej správy. Tento konštruktor je vhodný pre situácie, kde nie je žiadny kontext. Napríklad by ste chceli vedieť iba to, že zásobník je prázdny alebo plný. - Hádzateľné (reťazcová správa) vytvára a
Hoditeľné
sspráva
ako podrobná správa. Túto správu je možné odoslať používateľovi alebo prihlásiť.
Hoditeľné
poskytuje Reťazec getMessage ()
spôsob vrátenia podrobnej správy. Poskytuje tiež ďalšie užitočné metódy, ktoré uvediem neskôr.
Trieda Výnimka
Hoditeľné
má dve priame podtriedy. Jedna z týchto podtried je Výnimka
, ktorý popisuje výnimku spôsobenú externým faktorom (napríklad pokusom o čítanie z neexistujúceho súboru). Výnimka
deklaruje rovnaké konštruktory (s rovnakými zoznamami parametrov) ako Hoditeľné
, a každý konštruktor sa dovolá svojho Hoditeľné
náprotivok. Výnimka
dedí Hoditeľné
metódy; nedeklaruje žiadne nové metódy.
Java poskytuje mnoho tried výnimiek, ktoré priamo podtriedy Výnimka
. Tu sú tri príklady:
- CloneNotSupportedException signalizuje pokus o klonovanie objektu, ktorého trieda neimplementuje
Cloneable
rozhranie. Oba typy sú vjava.lang
balíček. - Výnimka IO signalizuje, že došlo k nejakému zlyhaniu I / O. Tento typ sa nachádza v
java.io
balíček. - Výnimka signalizuje, že pri analýze textu došlo k zlyhaniu. Tento typ nájdete v
java.text
balíček.
Všimnite si, že každý Výnimka
názov podtriedy končí slovom Výnimka
. Táto konvencia uľahčuje identifikáciu účelu triedy.
Spravidla budete podtriedou Výnimka
(alebo jedna z jeho podtried) s vašimi vlastnými triedami výnimiek (ktorých názvy by sa mali končiť na Výnimka
). Tu je niekoľko príkladov vlastných podtried:
public class StackFullException extends Exception {} public class EmptyDirectoryException extends Exception {private String directoryName; public EmptyDirectoryException (String message, String directoryName) {super (správa); this.directoryName = adresár; } public String getDirectoryName () {návrat adresáraName; }}
Prvý príklad popisuje triedu výnimiek, ktorá nevyžaduje podrobnú správu. Je to predvolené vyvolanie konštruktora noargument Výnimka ()
, ktorý sa dovoláva Hádzateľné ()
.
Druhý príklad popisuje triedu výnimiek, ktorej konštruktor vyžaduje podrobnú správu a názov prázdneho adresára. Konštruktor vyvolá Výnimka (reťazcová správa)
, ktorý sa dovoláva Hádzateľné (reťazcová správa)
.
Objekty inštancované z Výnimka
alebo jedna z jeho podtried (okrem RuntimeException
alebo jedna z jeho podtried) sú kontrolované výnimky.
Trieda RuntimeException
Výnimka
je priamo podtriedený RuntimeException
, ktorý popisuje výnimku, ktorá najpravdepodobnejšie vyplýva zo zle napísaného kódu. RuntimeException
deklaruje rovnaké konštruktory (s rovnakými zoznamami parametrov) ako Výnimka
, a každý konštruktor sa dovolá svojho Výnimka
náprotivok. RuntimeException
dedí Hoditeľné
metódy. Deklaruje žiadne nové metódy.
Java poskytuje mnoho tried výnimiek, ktoré priamo podtriedy RuntimeException
. Nasledujúce príklady sú všetci členmi java.lang
balenie:
- Aritmetická výnimka signalizuje neplatnú aritmetickú operáciu, napríklad pokus o vydelenie celého čísla číslom 0.
- IllegalArgumentException signalizuje, že metóde bol predložený nezákonný alebo nevhodný argument.
- NullPointerException signalizuje pokus o vyvolanie metódy alebo prístup k poľu inštancie prostredníctvom nulovej referencie.
Objekty inštancované z RuntimeException
alebo jedna z jeho podtried je nekontrolované výnimky.
Trieda Chyba
Hoditeľné
Ďalšia priama podtrieda je Chyba
, ktorý popisuje závažný (aj nenormálny) problém, s ktorým by sa rozumná aplikácia nemala pokúšať vyrovnať - napríklad nedostatok pamäte, pretečenie zásobníka JVM alebo pokus o načítanie triedy, ktorú nemožno nájsť. Páči sa mi to Výnimka
, Chyba
deklaruje rovnaké konštruktory ako Hoditeľné
, dedí Hoditeľné
metódy a nedeklaruje žiadnu zo svojich metód.
Môžete identifikovať Chyba
podtriedy z konvencie, ktorou sa názvy ich tried končia Chyba
. Príklady zahŕňajú OutOfMemoryError
, Chyba prepojenia
a StackOverflowError
. Všetky tri typy patria do skupiny java.lang
balíček.
Hádzanie výnimiek
Funkcia knižnice C upozorňuje na volací kód výnimky nastavením globálnej hodnoty errno
premenná na chybový kód a vrátenie chybového kódu. Naopak, metóda Java hodí objekt. Vedieť, ako a kedy hodiť výnimky, je základným aspektom efektívneho programovania v jazyku Java. Vyhodenie výnimky zahŕňa dva základné kroky:
- Použi
hodiť
vyhlásenie hodiť objekt výnimky. - Použi
hodí
doložka informovať kompilátora.
Neskôr sa časti zameriavajú na chytanie výnimiek a čistenie po nich, najskôr sa však dozvieme viac o hádzacích veciach.
Vyhlásenie hodu
Java poskytuje hodiť
príkaz hodiť objekt, ktorý popisuje výnimku. Tu je syntax súboru hodiť
vyhlásenie:
hodiť hádzateľná;
Objekt identifikovaný podľa hádzateľná
je príkladom Hoditeľné
alebo ktorákoľvek z jeho podtried. Zvyčajne však hádžete iba objekty inštancované z podtriedy Výnimka
alebo RuntimeException
. Tu je niekoľko príkladov:
hodiť novú FileNotFoundException ("nemôžem nájsť súbor" + názov súboru); throw new IllegalArgumentException ("argument odovzdaný do počtu je menší ako nula");
Vrhací prostriedok je vyhodený z aktuálnej metódy na JVM, ktorý skontroluje vhodnosť tejto metódy pre túto metódu. Ak sa nenájde, JVM odvinie zásobník volaní metód a hľadá najbližšiu metódu volania, ktorá dokáže spracovať výnimku opísanú v hode. Ak nájde túto metódu, odovzdá vrhaciu metódu handlerovi metódy, ktorého kód sa vykoná na spracovanie výnimky. Ak sa nenájde žiadna metóda na spracovanie výnimky, JVM sa ukončí vhodnou správou.
Doložka o hodoch
Musíte vyhodiť kompilátor, keď vyhodíte z metódy kontrolovanú výnimku. Urobte to pripojením a hodí
doložka k hlavičke metódy. Táto doložka má nasledujúcu syntax:
hodí checkedExceptionClassName (, checkedExceptionClassName)*
A hodí
doložka sa skladá z kľúčového slova hodí
nasledovaný čiarkami oddeleným zoznamom názvov tried kontrolovaných výnimiek vyhodených z metódy. Tu je príklad:
public static void main (String [] args) hodí ClassNotFoundException {if (args.length! = 1) {System.err.println ("usage: java ... classfile"); návrat; } Class.forName (args [0]); }
Tento príklad sa pokúša načítať súbor triedy identifikovaný argumentom príkazového riadku. Ak Class.forName ()
nemôže nájsť triedny súbor, hodí a java.lang.ClassNotFoundException
objekt, čo je kontrolovaná výnimka.
Overená kontroverzia výnimiek
The hodí
doložka a kontrolované výnimky sú kontroverzné. Mnoho vývojárov nenávidí, keď sú nútení špecifikovať hodí
alebo spracovať zaškrtnuté výnimky. Viac informácií sa dozviete z môjho článku Sú zaškrtnuté výnimky dobré alebo zlé? príspevok v blogu.