Eliminace dělení nulovou javou. Výjimečné situace v Javě - výjimka a chyba

Příkaz throw se používá k ručnímu vyvolání výjimky. Chcete-li to provést, musíte mít podtřídu Throwable, kterou lze získat buď jako parametr příkazu catch, nebo vytvořit pomocí operátoru new. Níže je uveden obecný formulář operátora hod,

hodObjectTypeVhazovatelný;

Po dosažení tohoto příkazu se normální provádění kódu okamžitě zastaví, takže následující příkaz nebude proveden. Nejbližší okolní blok try je zkontrolován, aby se zjistilo, zda existuje handler odpovídající vyvolané výjimce. Pokud se nějaký najde, řízení se přenese na něj. Pokud ne, testuje se další vnořený příkaz try a tak dále, dokud nebude nalezena odpovídající klauzule catch nebo obslužná rutina výjimek Java runtime nezastaví program a vytiskne stav zásobníku volání. Níže je uveden příklad, ve kterém je nejprve vytvořen objekt výjimky, poté příkaz throw vyvolá výjimku, načež je stejná výjimka vyvolána znovu - tentokrát kódem v sekci catch, který ji zachytil poprvé.

třída ThrowDemo(
static void demoproc() (
{
throw new NullPointerException("demo");
}
catch (NullPointerException e) (
System.out.println("chycen uvnitř demoproc");
hodit e;
}
}

zkus (
demoproc();
}
catch(NulPointerException e) (
System.out.println("recaught:" + e);
}
}
}

V tomto příkladu je výjimka zpracována ve dvou krocích. Hlavní metoda vytvoří kontext pro výjimku a zavolá demoproc. Metoda demoproc také nastaví kontext pro zpracování výjimky, vytvoří nový objekt NullPointerException a vyvolá výjimku pomocí příkazu throw. Výjimka je zachycena na dalším řádku v metodě demoproc a objekt výjimky je dostupný pro kód handleru prostřednictvím parametru „e“. Kód obslužné rutiny vytiskne zprávu, že byla vyvolána výjimka, a poté ji znovu vyvolá pomocí příkazu throw, což způsobí její předání obslužné rutině výjimky v hlavní metodě. Níže je výsledek získaný při spuštění tohoto příkladu.

C:\>JávaThrowDemo
chycen uvnitř demoproc
znovu zachyceno: java.lang.NullPointerException: demo

9.8. hází operátor

Pokud je metoda schopna vyvolávat výjimky, které sama nezpracovává, musí toto chování deklarovat, aby se volající metody mohly chránit před těmito výjimkami. K určení seznamu výjimek, které mohou být vyvolány metodou, se používá operátor throws. Pokud metoda explicitně (tj. pomocí příkazu throw) vyvolá výjimku odpovídající třídy, typ třídy výjimky musí být uveden v příkazu throws v deklaraci této metody. S ohledem na to je třeba naši předchozí syntaxi definice metody rozšířit následovně:

zadejte název_metody (seznam argumentů)házíseznam problémů ()

Následuje příklad programu, ve kterém se metoda procedury pokouší vyvolat výjimku, aniž by poskytla kód k jejímu zachycení nebo deklarovala výjimku v záhlaví metody. Takový programový kód nebude přeložen.

třídaThrowsDemo1 {
statickýprázdnotapostup()
{
System.out.println("vnitřní postup");
}
public static void main(String args) (
postup();
}
}

Abychom mohli tento příklad přeložit, budeme muset překladateli sdělit, že procedura může vyvolat výjimky typu IllegalAccessException a přidat kód do hlavní metody pro zpracování tohoto typu výjimky:

třída ThrowsDemo (
static void procedure() vyvolá výjimku IllegalAccessException
{
System.out.println(" vnitřní procedura");
hodit nový IllegalAccessException("demo");
}
public static void main(String aigs) (
pokus{
postup();
}
catch (IllegalAccessException e) (
System.out.println("chycen" + e);
}
}
}

Níže je výstup tohoto programu.

S:\>java ThrowsDemo
vnitřní procedura
zachyceno javaJangIllegalAccessException: demo

Dobrý den, Habr! Předkládám vaší pozornosti překlad článku Fixing 7 Common Java Exception Handling Mistakes od Thorbena Janssena.

Zpracování výjimky je jedním z nejběžnějších, ale ne nutně jedním z nejjednodušších úkolů. Toto je stále jedno z často diskutovaných témat mezi zkušenými týmy a existuje několik osvědčených postupů a běžných chyb, kterých byste si měli být vědomi.

Zde je několik věcí, kterým se při zpracování výjimek ve vaší aplikaci vyhnout.

Chyba 1: Deklarace java.lang.Exception nebo java.lang.Throwable

Jak již víte, musíte zaškrtnutou výjimku buď deklarovat, nebo zpracovat. Zaškrtnuté výjimky však nejsou jediné, které můžete zadat. V klauzuli throws můžete použít jakoukoli podtřídu java.lang.Throwable. Takže místo určení dvou různých výjimek, které vyvolá následující fragment kódu, můžete jednoduše použít výjimku java.lang.Exception v klauzuli throws.

Public void doNotSpecifyException() vyvolá výjimku ( doSomething(); ) public void doSomething() vyvolá výjimku NumberFormatException, IllegalArgumentException ( // něco udělejte)
Ale to neznamená, že to musíte udělat. Zadáním Exeption nebo Throwable je téměř nemožné je správně zpracovat při volání vaší metody. Jediná informace, kterou vaše volající metoda obdrží, je, že se něco může pokazit. Nesdílíte ale žádné informace o nějakých výjimečných událostech, které mohou nastat. Tyto informace skryjete za obecné důvody pro vyvolání výjimek. Je to ještě horší, když se vaše aplikace v průběhu času mění. Vyvolání obecných výjimek skryje všechny změny výjimek, které musí volající očekávat a zpracovat. To může vést k několika neočekávaným chybám, které je třeba najít v testovacím případě namísto chyby kompilátoru.

Použijte třídy betonu

Mnohem lepší je specifikovat nejkonkrétnější třídy výjimek, i když jich musíte použít více. To říká volajícímu, které výjimečné události má zpracovat. Umožňuje také aktualizovat klauzuli throw, když vaše metoda vyvolá další výjimku. Tímto způsobem jsou vaši klienti informováni o změnách a dokonce se jim zobrazí chyba, pokud změníte vyvolané výjimky. Takovou výjimku je mnohem snazší najít a zpracovat než výjimku, která se objeví pouze při spuštění konkrétního testovacího případu.

Public void specificSpecificExceptions() vyvolá výjimku NumberFormatException, IllegalArgumentException ( doSomething(); )

Chyba 2: Chytání obecných výjimek

Závažnost této chyby závisí na tom, jakou softwarovou komponentu implementujete a kde se setkáte s výjimkou. Možná by bylo dobré zachytit java.lang.Exception v hlavní metodě vaší Java SE aplikace. Pokud však implementujete knihovnu nebo pracujete na hlubších vrstvách vaší aplikace, měli byste raději zachytit určité výjimky.

To nabízí několik výhod. Tento přístup vám umožňuje zacházet s každou třídou výjimek odlišně a zabraňuje vám zachytit výjimky, které jste neočekávali.

Mějte však na paměti, že první blok catch, který zpracovává třídu výjimky nebo jednu z jejích supertříd, ji zachytí. Takže se ujistěte, že nejprve chytíte nejkonkrétnější třídu. V opačném případě vaše IDE zobrazí chybovou nebo varovnou zprávu o nedostupném bloku kódu.

Zkuste ( doSomething(); ) catch (NumberFormatException e) ( // zpracování výjimek NumberFormatException log.error(e); ) catch (IllegalArgumentException e) ( // zpracování výjimek IllegalArgumentException log.error(e); )

Chyba 3: Logování a házení výjimek

Toto je jedna z nejpopulárnějších chyb při zpracování výjimek v Javě. Může se zdát logické zaprotokolovat výjimku tam, kde je vyvolána, a poté ji předat volajícímu, který může implementovat specifické zpracování pro konkrétní případ použití. Ale neměli byste to dělat ze tří důvodů:

1. Nemáte dostatek informací o případu užití, který chce volající vaší metody implementovat. Výjimka může být součástí očekávaného chování a může být řešena klientem. V tomto případě není nutné jej registrovat. Tím se do souboru protokolu přidá falešná chybová zpráva, která by měla být filtrována vaším operačním týmem.

2. Zpráva protokolu neposkytuje žádné informace, které již nejsou součástí samotné výjimky. Jeho trasování a trasování zásobníku by měly obsahovat všechny potřebné informace o výjimečné události. Zpráva jej popisuje a trasování zásobníku obsahuje podrobnosti o třídě, metodě a řádku, na kterém k němu došlo.

3. Stejnou výjimku můžete zaznamenat vícekrát, když ji přihlásíte do každého bloku catch, který ji zachytí. To zkazí statistiky ve vašem monitorovacím nástroji a ztíží čtení souboru protokolu pro váš operační a vývojový tým.

Zaznamenejte výjimku tam, kde ji zpracováváte

Proto je nejlepší zaznamenat výjimku, když ji zpracováváte. Jako následující fragment kódu. Metoda doSomething vyvolá výjimku. Metoda doMore jej jednoduše specifikuje, protože vývojář nemá dostatek informací pro jeho zpracování. Poté je zpracována metodou doEvenMore, která také zapíše zprávu protokolu.

Public void doEvenMore() ( try ( doMore(); ) catch (NumberFormatException e) ( // zpracování výjimky NumberFormatException ) catch (IllegalArgumentException e) ( // zpracování výjimky IllegalArgumentException ) ) public void doMore() házíSoco(FormatException, Illegal doArgumentException ) public void doSomething() vyvolá výjimku NumberFormatException, IllegalArgumentException ( // něco udělat)

Chyba 4: Používání výjimek k řízení toku

Používání výjimek k řízení toku vaší aplikace je považováno za anti-vzor ze dvou hlavních důvodů:

V zásadě fungují jako příkaz Přejít na, protože zruší provádění bloku kódu a přejdou na první blok catch, který zpracovává výjimku. Díky tomu je kód velmi obtížně čitelný.

Nejsou tak účinné jako obecné řídicí struktury Java. Jak název napovídá, měli byste je používat pouze pro výjimečné události a JVM je neoptimalizuje stejným způsobem jako ostatní kódy, takže je lepší použít správné podmínky k rozdělení vašich smyček nebo příkazů if-else který blokový kód musí být proveden.

Chyba 5: Odstraňte příčinu výjimky

Někdy možná budete muset zabalit jednu výjimku do druhé. Možná se váš tým rozhodl použít specifickou obchodní výjimku s chybovými kódy a jednotným zpracováním. Na tomto přístupu není nic špatného, ​​pokud neřešíte příčinu.

Když vyvoláte novou výjimku, měli byste vždy nastavit původní výjimku jako příčinu. Jinak ztratíte zprávu a trasování zásobníku, které popisují výjimečnou událost, která způsobila vaši výjimku. Třída Exception a všechny její podtřídy poskytují několik metod konstruktoru, které berou původní výjimku jako parametr a nastavují ji jako příčinu.

Chyba 6: Zobecňování výjimek

Když zobecníte výjimku, zachytíte konkrétní výjimku, jako je NumberFormatException, a místo toho vyvoláte nespecifickou výjimku java.lang.Exception. To je podobné, ale ještě horší než první chyba, kterou jsem popsal v tomto článku. Nejen, že skryje informace o konkrétním případu chyby na vašem API, ale také ztíží přístup.

Public void doNotGeneralizeException() vyvolá výjimku ( try ( doSomething(); ) catch (NumberFormatException e) ( vyvolá novou výjimku(e); ) catch (IllegalArgumentException e) ( vyvolá novou výjimku(e); ) )
Jak můžete vidět v následujícím úryvku kódu, i když víte, jaké výjimky může metoda způsobit, nemůžete je jednoduše zachytit. Musíte zachytit generickou třídu Exception a poté zkontrolovat typ její příčiny. Tento kód je nejen těžkopádný na implementaci, ale je také obtížně čitelný. Ještě horší to bude, pokud tento přístup zkombinujete s chybou 5. Tím se odstraní všechny informace o výjimečné události.

Zkuste ( doNotGeneralizeException(); ) catch (Exception e) ( if (e.getCause() instanceof NumberFormatException) ( log.error("NumberFormatException: " + e); ) else if (e.getCause() instanceof IllegalArgumentException) ( log .error("IllegalArgumentException: " + e else ( log.error("Neočekávaná výjimka: " + e); ) );
Jaký přístup je tedy nejlepší?

Buďte konkrétní a uveďte důvod, proč k výjimce došlo.

Výjimky, které vyvoláte, by měly být vždy co nejkonkrétnější. A pokud zabalíte výjimku, měli byste také nastavit původní výjimku jako příčinu, abyste neztratili trasování zásobníku a další informace popisující výjimečnou událost.

Zkuste ( doSomething(); ) catch (NumberFormatException e) ( vyvolá novou výjimku MyBusinessException(e, ErrorCode.CONFIGURATION_ERROR); ) catch (IllegalArgumentException e) ( vyvolá novou výjimku MyBusinessException(e, ErrorCode.UNEXPECTED); )

Chyba 7: Přidání zbytečných konverzí výjimek

Jak jsem vysvětlil dříve, může být užitečné zabalit výjimky do vlastních výjimek, pokud jako příčinu nastavíte původní výjimku. Někteří architekti však jdou přes palubu a zavádějí speciální třídu výjimek pro každou architektonickou úroveň. Takže zachytí výjimku ve vrstvě persistence a hodí ji do MyPersistenceException. Obchodní vrstva to zachytí a zabalí do MyBusinessException a to pokračuje, dokud nedosáhne vrstvy API nebo není zpracováno.

Public void persistCustomer(Customer c) vyvolá MyPersistenceException ( // persist a Customer ) public void manageCustomer(Customer c) vyvolá MyBusinessException ( // správa Customer try ( persistCustomer(c); ) catch (MyPersistenceException e) ( vyvolá novou MyBusinessException(e , e.getCode() ) ) public void createCustomer(Customer c) vyvolá MyApiException ( // vytvoření Customer try ( manageCustomer(c); ) catch (MyBusinessException e) ( throw new MyApiException(e, e.getCode()) )))
Je snadné vidět, že tyto další třídy výjimek neposkytují žádnou výhodu. Jednoduše zavedou další vrstvy, které zabalí výjimku. A i když by bylo zábavné zabalit dárek do spousty barevného papíru, není to dobrý přístup k vývoji softwaru.

Nezapomeňte doplnit informace

Jen přemýšlejte o kódu, který potřebuje zpracovat výjimku, nebo o sobě, když potřebujete najít problém, který výjimku způsobil. Nejprve musíte prolomit několik vrstev výjimek, abyste našli hlavní příčinu. A dodnes jsem nikdy neviděl aplikaci, která by zvolila tento přístup a přidala užitečné informace s každou vrstvou výjimky. Buď zobecňují chybovou zprávu a kód, nebo poskytují nadbytečné informace.

Buďte tedy opatrní s počtem vlastních tříd výjimek, které zavádíte. Vždy byste si měli položit otázku, zda nová třída výjimky poskytuje další informace nebo jiné výhody. Ve většině případů k dosažení tohoto cíle nepotřebujete více než jednu úroveň vlastních výjimek.

Public void persistCustomer(Customer c) ( // persist a Customer ) public void manageCustomer(Customer c) vyvolá MyBusinessException ( // Správa zákazníka vyvolá novou MyBusinessException(e, e.getCode()); ) public void createCustomer(Customer c) vyvolá MyBusinessException ( // vytvoření Customer manageCustomer(c); )


2. Jaká je hierarchie výjimek.
3. Je možné/potřebné ošetřit chyby jvm?
4. Jaké jsou různé způsoby zpracování výjimek?
5. Co znamená klíčové slovo throws?
6. Co je zvláštního na závěrečném bloku? Je vždy splněno?
7. Může při zachytávání výjimek existovat blok pro chytání?
8. Napadá vás situace, kdy se konečný blok neprovede?
9. Může jeden catch blok zachytit více výjimek (ze stejné a různých větví dědičnosti)?
10. Co víte o zaškrtnutých/nezaškrtnutých výjimkách?
11. Co je zvláštního na RuntimeException?
12. Jak napsat vlastní (“vlastní”) výjimku? Jaké motivy vás povedou při výběru typu výjimky: zaškrtnutá/nezaškrtnutá?
13. Který operátor umožňuje vynutit vyvolání výjimky?
14. Existují další podmínky pro metodu, která by mohla potenciálně vyvolat výjimku?
15. Může metoda main vyvolat výjimku externě, a pokud ano, kde bude tato výjimka zpracována?
16. Pokud je příkaz return obsažen jak v bloku catch, tak v bloku nakonec, který z nich je „důležitější“?
17. Co víte o chybě OutOfMemoryError?
18. Co víte o SQLException? Do jakého typu zaškrtnutého nebo nezaškrtnutého patří a proč?
19. Co je chyba? Kdy se používá Error? Uveďte příklad chyby.
20. Která konstrukce se používá v Javě ke zpracování výjimek?
21. Předpokládejme, že existuje blok try-finally. V bloku try došlo k výjimce a provádění se přesunulo do bloku final. Výjimka nastala také v bloku final. Která z těchto dvou výjimek „vyhodí“ z bloku try-finally? Co se stane s druhou výjimkou?
22. Předpokládejme, že existuje metoda, která dokáže vyvolat výjimku IOException a FileNotFoundException, v jakém pořadí by měly bloky catch jít? Kolik bloků catch bude provedeno?

Odpovědi

1. Definujte pojem „výjimka“

Výjimka je problém (chyba), ke které dochází během provádění programu. V mnoha případech mohou nastat výjimky, např.

  1. Uživatel zadal nesprávné údaje.
  2. Soubor, ke kterému program přistupuje, nebyl nalezen.
  3. Během přenosu dat bylo ztraceno síťové připojení k serveru. Atd.

Všechny výjimky v Javě jsou objekty. Lze je tedy generovat nejen automaticky, když nastane výjimečná situace, ale i vytvářet samotný vývojář.

2. Jaká je hierarchie výjimek.

Výjimky jsou rozděleny do několika tříd, ale všechny mají společného předka - třídu Throwable. Jeho potomky jsou podtřídy Exception a Error.

Výjimky jsou výsledkem problémů v programu, které jsou v zásadě řešitelné a předvídatelné. Například k dělení nulou došlo v celých číslech.

Chyby jsou závažnější problémy, které specifikace Java uvádí a které byste se neměli pokoušet řešit ve svém vlastním programu, protože se jedná o problémy na úrovni JVM. Například k výjimkám tohoto druhu dochází, pokud dojde paměť dostupná pro virtuální počítač. Program stále nebude schopen poskytnout další paměť pro JVM.

V Javě jsou všechny výjimky rozděleny do dvou typů: kontrolované výjimky (zaškrtnuté) a nekontrolované výjimky (nezaškrtnuté), které zahrnují chyby (Errors) a runtime výjimky (RuntimeExceptions, potomek třídy Exception).

Certifikované výjimky jsou chyby, které mohou a měly by být zpracovány v programu všichni potomci třídy Exception (ale ne RuntimeException).

3. Je možné/potřebné ošetřit chyby jvm?

Můžete to zpracovat, ale neměli byste to dělat. Vývojář nemá k dispozici nástroje pro řešení systémových chyb a chyb virtuálních strojů.

4. Jaké jsou různé způsoby zpracování výjimek?

Java má pět klíčových slov pro zpracování výjimek:

  1. pokus— toto klíčové slovo se používá k označení začátku bloku kódu, který by mohl potenciálně vést k chybě.
  2. chytit— klíčové slovo pro označení začátku bloku kódu určeného k zachycení a zpracování výjimek.
  3. konečně— klíčové slovo pro označení začátku bloku kódu, které je volitelné. Tento blok je umístěn za posledním blokem „chytit“. Kontrola je obvykle stejně předána do bloku „konečně“.
  4. hod- slouží ke generování výjimek.
  5. hází

Obecná forma konstrukce pro „zachycení“ výjimečné situace je následující:

Více podrobností http://www.quizful.net/post/java-exceptions

5. Co znamená klíčové slovo throws?

hází— klíčové slovo, které je zapsáno v podpisu metody a označuje, že metoda může potenciálně vyvolat výjimku zadaného typu.

6. Co je zvláštního na závěrečném bloku? Je vždy splněno?

Když je vyvolána výjimka, provádění metody je směrováno po nelineární cestě. To může být zdrojem problémů. Například metoda otevře soubor při vstupu a zavře jej při ukončení. Aby se zabránilo zmeškanému uzavření souboru v důsledku zpracování výjimek, byl navržen mechanismus konečně.

Klíčové slovo konečně vytvoří blok kódu, který bude proveden po dokončení bloku zkusit/chytit, ale před kódem, který za ním následuje. Blok bude proveden bez ohledu na to, zda je vyvolána výjimka nebo ne. Operátor konečně není vyžadováno, nicméně každý operátor pokus vyžaduje buď chytit nebo konečně. Kód v bloku konečně bude splněno Vždy.

7. Může při zachytávání výjimek existovat blok pro chytání?

Tento zápis je platný, pokud existuje klauzule try() nakonec(). Ale takový zápis nemá moc smysl, pořád je lepší mít záchytný blok, ve kterém se potřebná výjimka zpracuje.

Řetězec x = "z"; zkuste ( x="234"; ) nakonec ( x = "Konečně"; )

Řetězec x = "z" ;

zkus (

x = "234" ;

) konečně (

x = "Konečně" ;

8. Napadá vás situace, kdy se konečný blok neprovede?

Poslední blok není vždy proveden, například v této situaci:

zkuste ( System.exit(0); ) catch (Exception e) ( e.printStackTrace(); ) nakonec ( )

zkus (

Systém. exit(0);

) chytit (výjimka e) (

E. printStackTrace();

) konečně ( )

Zde je konečně nedostupný, protože systém ukončí program. Obecně řečeno: když jvm zemře, nemá na to čas (zde můžete přijít s dalšími příklady, jak zabít jvm a odpovědět na otázku v názvu).

9. Může jeden catch blok zachytit více výjimek (ze stejné a různých větví dědičnosti)?

V Java 7 Je k dispozici nová konstrukce, která vám umožňuje zachytit více výjimek jedním catch blokem:

try ( ... ) catch(IOException | SQLException ex) ( logger.log(ex); throw ex; )

zkus (

. . .

) catch (IOException | SQLException ex) (

záznamník. log(ex);

hodit ex ;

10. Co víte o zaškrtnutých/nezaškrtnutých výjimkách?

Všechny výjimečné situace jsou rozděleny na „zaškrtnuté“ a „nezaškrtnuté“ (viz obrázek na začátku článku). Tato vlastnost je vlastní „oddenku“ (Throwable, Error, Exception, RuntimeException) a je zděděna. Ve zdrojovém kódu třídy výjimek není vidět.
V dalších příkladech mějte na paměti, že jsou kontrolovány možnosti Throwable a Exception a všichni jejich potomci (kromě potomků Error a RuntimeException).
- Error a RuntimeException a všichni jejich potomci - nezaškrtnuto
zkontrolovaná výjimka = zkontrolovaná výjimka zkontrolovaná kompilátorem.

Téma je dostatečně široké, aby se vešlo do jedné odpovědi. Můžete se například podívat na Golovachovy příklady: http://habrahabr.ru/company/golovachcourses/blog/225585/

A také z quizful.net

1. Kontrolované výjimky jsou ty, které musí být zpracovány blokem catch nebo popsány v podpisu metody. Nezaškrtnuté nemusí být zpracovány ani popsány.
2. Nezaškrtnuté výjimky v Javě - zděděné z RuntimeException, zaškrtnuté - z výjimky (nezahrnuje nezaškrtnuté).

Zaškrtnuté výjimky se liší od nekontrolovaných výjimek v Javě tím, že:
1) Dostupnost\zpracování Zkontrolováno výjimky se kontrolují ve fázi kompilace. Dostupnost\zpracování Nezaškrtnuto dochází k výjimkám během provádění.

11. Co je zvláštního na RuntimeException?

public class RuntimeException rozšiřuje výjimku - základní třídu pro běhové chyby. Odkazuje na neošetřené výjimky (nezachyceno\nezaškrtnuto). Jak je uvedeno v popisu třídy, jedná se o nadtřídu, jejíž výjimky mohou být vyvolány během normálního provozu JVM.

12. Jak napsat vlastní (“vlastní”) výjimku? Jaké motivy vás povedou při výběru typu výjimky: zaškrtnutá/nezaškrtnutá?

Musíte zdědit ze základní třídy požadovaný typ výjimky (například Exception nebo RuntimeException).

veřejná třída ExcClass rozšiřuje výjimku ( private String someString; public ExcClass (String string) ( this.someString = řetězec; System.out.println("Exception ExcClass"); ) public void myOwnExceptionMsg() ( System.err.println("Toto je masáž výjimek pro řetězec: " + someString); ) ) veřejná třída TestExc ( public static void main(String args) ( try (String s = "SomeString"; vyvolání nové ExcClass(s); ) catch (ExcClass ex) (ex .myOwnExceptionMsg() ) ) //Výjimka výstupu ExcClass Toto je masáž výjimek pro řetězec: SomeString

veřejná třída ExcClass rozšiřuje výjimku (

private String someString ;

public ExcClass(řetězec řetězce) (

tento. someString = řetězec ;

Systém. ven . println("Výjimka ExcClass");

public void myOwnExceptionMsg() (

Systém. chybovat. println( "Toto je výjimečná masáž pro strunu:"+nějakýString);

veřejná třída TestExc(

zkus (

String s = "SomeString" ;

hodit nové ExcClass(y);

) catch (ExcClass ex) (

např. myOwnExceptionMsg();

//Závěr

Výjimka ExcClass

Toto je výjimečná masáž pro strunu: SomeString

Musíte se řídit definicí typu výjimky. V závislosti na tom, co chcete zpracovat nebo vidět, musíte dědit z požadované třídy.

13. Který operátor umožňuje vynutit vyvolání výjimky?

hodit novou výjimku();

14. Existují další podmínky pro metodu, která by mohla potenciálně vyvolat výjimku?

Pokud se jedná o kontrolovanou výjimku, musí být deklarována v podpisu metody.

Public void someMethod() vyvolá výjimku ( )

public void someMethod() vyvolá výjimku(

15. Může metoda main vyvolat výjimku externě, a pokud ano, kde bude tato výjimka zpracována?

Možná bude přenesen do Java Virtual Machine (JVM).

16. Pokud je příkaz return obsažen jak v bloku catch, tak v bloku nakonec, který z nich je „důležitější“?

Vrátí se z konečného bloku.

Public static void main(String args) ( String what = method(); System.out.println(co); ) public static String method() ( try ( return "SomeString"; ) nakonec ( return "Finally message"; ) ) //Výstup Konečně zpráva

public static void main (String args) (

String what = metoda () ;

Systém. ven . println(co);

public static String method() (

zkus (

return "SomeString" ;

) konečně (

return "Konečně zpráva" ;

//Závěr

Konečně zpráva

17. Co víte o chybě OutOfMemoryError?

OutOfMemoryError je vyvolán, když Java Virtual Machine není schopen alokovat (přidělit) objekt kvůli nedostatku paměti a garbage collector nemůže uvolnit další.

Paměťová oblast obsazená procesem Java se skládá z několika částí. Typ chyby OutOfMemoryError závisí na tom, kterému z nich došlo místo.

1. java.lang.OutOfMemoryError: Prostor haldy Java
Na hromadě není dostatek místa, což je oblast paměti, do které jsou umístěny objekty vytvořené programově ve vaší aplikaci. Velikost je určena parametry -Xms a -Xmx. Pokud se pokusíte vytvořit objekt a v haldě nezůstane žádné místo, zobrazí se tato chyba. Problém obvykle spočívá v úniku paměti, kterých je velké množství a internet je prostě plný článků na toto téma.

2. java.lang.OutOfMemoryError: Prostor PermGen
K této chybě dochází, když není dostatek místa v oblasti Permanent, jejíž velikost je určena parametry -XX:PermSize a -XX:MaxPermSize.

3. java.lang.OutOfMemoryError: Překročen limit režijních nákladů GC
K této chybě může dojít jak při přetečení první, tak druhé oblasti. Je to způsobeno tím, že zbývá málo paměti a GC neustále pracuje a snaží se uvolnit místo. Tuto chybu lze deaktivovat pomocí parametru -XX:-UseGCOverheadLimit, ale samozřejmě by se neměla deaktivovat, ale buď vyřešit problém s únikem paměti, nebo alokovat více místa nebo změnit nastavení GC.

4. java.lang.OutOfMemoryError: nelze vytvořit nové nativní vlákno

Vyhozen, když nelze vytvořit další vlákna.

Více podrobností v článku http://habrahabr.ru/post/117274/

18. Co víte o SQLException? Do jakého typu zaškrtnutého nebo nezaškrtnutého patří a proč?

SQLException poskytuje informace o chybách přístupu k databázi nebo jiných chybách souvisejících s databází.

SQLException patří mezi kontrolované výjimky, což znamená, že je kontrolována ve fázi kompilace.

Debata o tomto typu výjimek vede k tomu, že vývojář musí tuto výjimku v kódu neustále zpracovávat, i když většina chyb se vyskytuje během provádění programu, tedy podle mnohých by bylo lepší klasifikovat to jako nekontrolované výjimky za běhu.

try ( // proveďte nějaké volání SQL ) catch (SQLException e) ( // zaprotokolujte návrat výjimky; // a vzdejte se )

zkus (

// proveďte nějaké volání SQL

) catch ( SQLException e ) (

//zaznamenat výjimku

vrátit se ; // a vzdát se

Argumentem Joshuy Blocha z Effective Java Second Edition je, že testovatelnost SQLException je pokusem donutit vývojáře, aby výjimku zvládli a zabalili ji do nové úrovně abstrakce.

19. Co je chyba? Kdy se používá Error? Uveďte příklad chyby.

Chyby jsou závažnější problémy, které specifikace Java uvádí a které byste se neměli pokoušet řešit ve svém vlastním programu, protože se jedná o problémy na úrovni JVM. Například k výjimkám tohoto druhu dochází, pokud dojde paměť dostupná pro virtuální počítač.

Podívejte se například na obrázek hierarchie výjimek na začátku článku. Jako příklad - OutOfMemoryError.

20. Která konstrukce se používá v Javě ke zpracování výjimek?

Můžete použít try-catch-finally as Java 7 try-with-resources. První způsob:

try( //zde je kód, který by mohl potenciálně vést k chybě) catch(SomeException e)( //v závorce je uvedena třída konkrétní očekávané chyby //zde jsou popsány akce zaměřené na zpracování výjimek) nakonec( //provedeno v každém případě (zablokování je volitelné))

Zkuste se zdroji:

Starý způsob BufferedReader br = nový BufferedReader(new FileReader(cesta));

try ( return br.readLine(); ) nakonec ( if (br != null) ( br.close(); ) ) JDK 7 try (BufferedReader br = new BufferedReader(new FileReader(cesta))) ( return br.readLine ();

Starý způsob

zkus (

BufferedReader br = new BufferedReader(new FileReader(cesta));

) konečně (

vrátit se br. readLine();

if (br != null ) (

br. blízko();

JDK 7

zkuste (BufferedReader br =

BufferedReader br = new BufferedReader(new FileReader(cesta));

new BufferedReader (nový FileReader (cesta) ) (

Podívejte se také na odpověď na otázku „Jaké jsou způsoby zpracování výjimek?“

21. Předpokládejme, že existuje blok try-finally. V bloku try došlo k výjimce a provádění se přesunulo do bloku final. Výjimka nastala také v bloku final. Která z těchto dvou výjimek „vyhodí“ z bloku try-finally? Co se stane s druhou výjimkou?

public class TestExc ( public static void main(String args) ( Exception ex = twoExceptionsMethod(); System.out.println(ex.getClass()); String s = twoExceptionsMethod2(); System.out.println(s); ) public static Exception twoExceptionsMethod() ( try ( return new IndexOutOfBoundsException(); ) nakonec ( return new NullPointerException(); ) ) public static String twoExceptionsMethod2() ( try ( throw new NullPointerException(); ) catch (NullPointerException ex) ( System. out.println(ex.getMessage()+ " catchBlock");; ) nakonec ( Exception ex2 = new Exception(); return ex2.getMessage() + "finallyBlock"; ) ) ) //Výstupní třída java.lang.NullPointerException null catchBlock null nakonecBlock

veřejná třída TestExc(

public static void main (String args) (

Exception ex = twoExceptionsMethod();

Systém. ven . println(např. getClass());

Co je výjimka?

Výjimka je událost, která přeruší normální průběh provádění. Jedná se o narušení během provádění programu Java.

V tomto tutoriálu se naučíte-

Existují dva typy chyb:

  1. Chyby času kompilace
  2. Runtime chyby

Chyby v době kompilace lze opět rozdělit do dvou typů:

  • Chyby syntaxe
  • Sémantické chyby

Příklad syntaxe:

Místo deklarování int a; omylem jste to prohlásili jako v a; pro který kompilátor vyvolá chybu.

Příklad: Deklarovali jste proměnnou int a; a po několika řádcích kódu znovu deklarujete celé číslo jako int a; . Všechny tyto chyby jsou zvýrazněny při kompilaci kódu.

Příklad chyb za běhu

Runtime chyba se nazývá an Výjimky chyba. Je to jakákoli událost, která přeruší normální průběh provádění programu.

Příklady výjimek jsou aritmetická výjimka, výjimka nulového ukazatele, výjimka Dělit nulou atd.

Výjimky v Javě jsou něco, co je mimo kontrolu vývojářů.

Proč potřebujeme výjimku?

Předpokládejme, že jste zakódovali program pro přístup k serveru. Věci fungovaly dobře, když jste vyvíjeli kód.

Během skutečného produkčního běhu je server mimo provoz. Když se k němu váš program pokusil získat přístup, vyvolá se výjimka.

Jak zacházet s výjimkami

Doposud jsme viděli, že výjimka je mimo kontrolu vývojáře, ale obviňování selhání kódu z environmentálních problémů není řešením. Potřebujete robustní programování, které se stará o výjimečné situace Obsluha výjimek.

V našem příkladu by dobrým zpracováním výjimek bylo připojení k záložnímu serveru, když je server mimo provoz.

Chcete-li to implementovat, zadejte svůj kód pro připojení k serveru (pomocí tradičních podmínek if a else).

Zkontrolujete, zda je server mimo provoz. Pokud ano, napište kód pro připojení k záložnímu serveru.

Taková organizace kódu pomocí smyček "if" a "else" není účinná, pokud váš kód musí zpracovat více výjimek java.

Class connect( if(Server Up)( // kód pro připojení k serveru ) else( // code pro připojení k BACKUP serveru ) )

Zkuste Catch Block

Java poskytuje vestavěné výjimečné ovládání.

  1. Normální kód jde do a POKUS blok.
  2. Kód zpracování výjimek jde do CHYTIT blok

V našem příkladu bude blok TRY obsahovat kód pro připojení k serveru. Blok CATCH bude obsahovat kód pro připojení k záložnímu serveru.

V případě, že je server zapnutý, bude kód v bloku CATCH ignorován. V případě, že je server mimo provoz, vyvolá se výjimka a provede se kód v bloku catch.

Takto je výjimka řešena v Javě.

Syntaxe pro použití try & catch

Try( statement(s) ) catch (exceptiontype name)( statement(s) )

Krok 1) Zkopírujte následující kód do editoru

Třída JavaException ( public static void main(String args)( int d = 0; int n = 20; int zlomek = n/d; System.out.println("End Of Main"); ) )

Krok 2) Uložte soubor a zkompilujte kód. Spusťte program pomocí příkazu java JavaException

Krok 3) Aritmetická výjimka - dělení nulou je zobrazeno jako níže pro řádek #5 a řádek #6 se nikdy neprovede

Krok 4) Nyní se podívejme, jak nám try and catch pomůže zvládnout tuto výjimku. Výjimku způsobující řádek kódu vložíme do pokus blok, následovaný a chytit blok. Zkopírujte následující kód do editoru.

Třída JavaException ( public static void main(String args) ( int d = 0; int n = 20; try ( int zlomek = n / d; System.out.println("Tento řádek nebude proveden"); ) catch ( ArithmeticException e) ( System.out.println("Zablokováno kvůli výjimce = " + e); ) System.out.println("Konec hlavní" ) )

Krok 5) Uložte, zkompilujte a spusťte kód. Získáte následující výstup

Jak vidíte, výjimka se zpracuje a provede se také poslední řádek kódu. Všimněte si také, že řádek #7 nebude proveden, protože jakmile je vyvolána výjimka, tok řízení skočí do bloku záchytu.

Poznámka: Objekt AritmeticException "e" nese informace o výjimce, ke které došlo, což může být užitečné při provádění akcí obnovy.

Hierarchie tříd Java Exception

Po provedení jednoho příkazu catch jsou ostatní vynechány a provádění pokračuje po bloku try/catch. Vnořené bloky catch sledují hierarchii výjimek.
  • Všechny třídy výjimek v Javě rozšiřují třídu „Throwable“. Throwable má dvě podtřídy, Error a Exception
  • Třída Error definuje výjimku nebo problémy, které za normálních okolností náš program neočekává, například chyba paměti, chyba hardwaru, chyba JVM atd.
  • Třída Exception představuje výjimky, které může náš program zpracovat, a náš program lze z této výjimky obnovit pomocí bloku try and catch
  • Runtime výjimka je podtřídou třídy výjimky. Výjimka tohoto typu představuje výjimku, která se vyskytuje v době běhu a kterou nelze sledovat v době kompilace. Vynikajícím příkladem toho samého je dělení nulovou výjimkou nebo výjimkou s nulovým ukazatelem atd
  • Výjimka IO je generována během vstupních a výstupních operací
  • Přerušené výjimky v Javě se generují během více vláken.
Příklad: Pochopit vnořování bloků pokusu a chycení

Krok 1)

Třída JavaException ( public static void main(String args) ( try ( int d = 1; int n = 20; int zlomek = n / d; int g = ( 1 ); g = 100; ) /*catch(Exception e) ( System.out.println("V záchytných hodinách kvůli výjimce = "+e); )*/ catch (ArithmeticException e) ( System.out.println("V záchytných hodinách kvůli výjimce = " + e); ) catch (ArrayIndexOutOfBoundsException e) ( System.out.println("V hodině catch kvůli výjimce = " + e); ) System.out.println("End Of Main" ) )

Krok 2) Uložte soubor a zkompilujte kód. Spusťte program pomocí příkazu, java JavaException.

Krok 3) Je vygenerována výjimka ArrayIndexOutOfBoundsException. Změňte hodnotu int d na 0. Uložte, zkompilujte a spusťte kód.

Krok 4) Musí být vygenerována výjimka ArithmeticException.

Krok 5) Odkomentujte řádek #10 až řádek #12. Uložte, zkompilujte a spusťte kód.

Krok 6) Chyba kompilace? Je to proto, že Exception je základní třída AritmeticException Exception. Jakákoli výjimka, která je vyvolána ArithmeticException, může být také zpracována třídou Exception. Blok catch ArithmeticException tedy nikdy nedostane šanci být proveden, takže je nadbytečný. Proto chyba kompilace.

Java Konečně Block

Poslední blok je provedeny bez ohledu na vznesenou výjimku v bloku try. To je volitelný použít s blokem try.

Zkuste ( statement(s) ) catch (ExceptiontType name) ( statement(s) ) nakonec ( statement(s) )

V případě, že je v bloku try vyvolána výjimka, je nakonec blok proveden po provedení bloku catch.

Krok 1) Zkopírujte následující kód do editoru.

Třída JavaException ( public static void main(String args)( try( int d = 0; int n =20; int zlomek = n/d; ) catch(ArithmeticException e)( System.out.println("V hodině catch to Exception = "+e); ) nakonec( System.out.println("Uvnitř bloku nakonec"); ) ) )

Krok 2) Uložte, zkompilujte a spusťte kód.

Krok 3) Očekávaný výstup. Nakonec se blok provede, i když je vyvolána výjimka.

Krok 4) Změňte hodnotu proměnné d = 1. Uložte, zkompilujte a spusťte kód a sledujte výstup. Spodní část formuláře

Shrnutí:

  • An Výjimkou je chyba za běhu který přeruší normální průběh provádění programu. Přerušení během provádění programu se označuje jako chyba nebo výjimka.
  • Chyby jsou rozděleny do dvou kategorií
    • Chyby při kompilaci – Syntaktické chyby, sémantické chyby
    • Runtime chyby-výjimka
  • A robustní program by měl zvládnout všechny výjimky a pokračovat v normálním průběhu provádění programu. Java poskytuje vestavěnou výjimečnou metodu manipulace
  • Exception Handler je sada kódů, které zpracovává výjimku. Výjimky lze v Javě ošetřit pomocí try & catch.
  • Zkuste blokovat: Normální kód jde na tento blok.
  • Záchytný blok: Pokud je v normálním kódu chyba, přejde do tohoto bloku

O čem a proč je tento článek?

Článek pojednává o výjimkách v jazyce Java, metodách jejich zpracování a některých funkcích práce s výjimkami. Tento článek byl napsán pro seminář o technologiích Java vedený společností i.Point.

Jaké jsou výjimky?

Výjimky nebo výjimečné události jsou události, které narušují normální průběh provádění programu.

Pokaždé, když se během provádění programu vyskytne chyba, program vyvolá výjimku – v tuto chvíli je vytvořen speciální objekt výjimky (exception-object), odteď jej budeme jednoduše nazývat výjimka. Tento objekt obsahuje informace o chybě, která se vyskytla: typ chyby a také záznam o stavu programu v době, kdy k chybě došlo. Zavolá se vyvolání výjimky a její předání do běhového prostředí vyvolání výjimky(výjimka házení). Podívejme se, jak jsou vyvolány výjimky při spouštění programu v Javě:

Během provádění první metody došlo k nějakému problému, po kterém byla vyvolána výjimka. Ve chvíli, kdy je vyvolána výjimka, Java začne hledat pro ni vhodný handler a předá objekt do zásobníku volání, dokud není nalezen handler výjimky.

Typy výjimek v Javě

Podívejme se na hierarchii tříd objektů výjimek v Javě:

Jak vidíme, všechny výjimky mají společného předka – Throwable. Má dvě důležité podtřídy – Exception a Error. Výjimky jsou výsledkem problémů, se kterými se setkáte v rámci programu, které jsou v zásadě řešitelné a předvídatelné. Chyby jsou závažnější problémy, o které by se podle specifikace Java nemělo v racionálně napsané aplikaci pokoušet (například chyba OutOfMemoryError nastane, když JVM nemá dostatek paměti ke spuštění programu). Kromě toho má Exception důležitého potomka, RuntimeException. Tato třída a její potomci představují výjimky, které jsou vyvolány během „normálního provozu stroje Java“ (příklady takových výjimek zahrnují pokusy o použití nulových odkazů na objekt, dělení nulou nebo přetečení pole).

V Javě jsou všechny výjimky rozděleny do tří typů: kontrolované výjimky (checked), chyby (Errors) a runtime výjimky (RuntimeExceptions) – poslední dva typy jsou také sloučeny do kategorie nekontrolovaných výjimek. jaký je v tom rozdíl? Všechny velmi jednoduše řízené výjimky jsou ty chyby, které lze zpracovat během provádění programu, jak jste možná uhodli, všichni potomci třídy Exception (ale ne RuntimeException) patří do tohoto typu. Zaškrtnuté výjimky musí být zpracovány v kódu programu, musí být zpracovány buď zahrnutím do bloku try-catch, nebo deklarovány v podpisu metody.

Nekontrolované výjimky nevyžadují povinné zpracování, protože představují situace, kdy chyba nezávisí přímo na programátoru (například došlo k selhání hardwaru), nebo takové, kdy nemá smysl chybu řešit, protože je snazší provádět změny v kódu – ty zahrnují všechny potomky tříd Error a RuntimeException.

Jak zacházet s výjimkami?

Všechny moderní implementace jazyka Java se drží principu vyřizování nebo vyhlašování výjimek(The Catch or Specify Requirement), který uvádí, že kód, který má potenciál vyvolat řízenou výjimku, musí být buď uzavřen v bloku try-catch (proto v bloku catch poskytujeme obsluhu pro výjimku), nebo musíme oznámitže naše metoda může takovou výjimku vyvolat (za klíčovým slovem throws, za názvem metody).

Podívejme se na několik příkladů:

//Poznámka: Tato třída se nezkompiluje záměrně! importovat java. io .*; importovat java. util. vektor ; public class ListOfNumbers ( private Vector vector ; private static final int VELIKOST = 10 ; public ListOfNumbers () ( vector = new Vector (SIZE ) ; for (int i = 0 ; i< SIZE ; i ++ ) { vector . addElement (new Integer (i )) ; } } public void writeList () { < SIZE ; i ++ ) { out . println (" Value at: " + i + " = " + vector . elementAt (i )) ; } out . close () ; } }

Tento kód se nezkompiluje, protože Konstruktor FileWriter vyžaduje, abychom zpracovali IOException. Správně napsaný kód by měl vypadat nějak takto:

Pokus( //Neošetřená kontrolovaná výjimka IOException PrintWriter out = nový PrintWriter (nový FileWriter ( " OutFile.txt " )) ; for (int i = 0; i< SIZE ; i ++ ) { // metoda elementAt vyvolá nekontrolovanou výjimku ArrayIndexOutOfBoundsException ven . println(" Hodnota v: " + i + " = " + vektor . elementAt (i)) ; ) catch (IOException e)( //Pokoušíme se nějak napravit situaci, pokud došlo k chybě při vytváření souboru OutFile.txt) catch (výjimka e)( //Pokud je v bloku try vygenerována výjimka bez IOException, kontrola zde projde) konečně ( //V každém případě musíme soubor zavřít. if (out != null )( out . close () ; ) )

Takto zacházíme s IOException. Dávejte pozor na pořadí, ve kterém jsou bloky catch deklarovány - pokud je prohodíte, kód se nezkompiluje, protože IOException je podtřída Exception, pak se kód pro zpracování IOException stane nedostupným a kompilátor vyvolá chybu. Poslední blok si zaslouží zvláštní pozornost - kód v tomto bloku je vždy spuštěn, bez ohledu na to, co se stalo v blocích try and catch.

Kromě přímého zpracování výjimky pomocí bloku try-catch ji můžeme jednoduše deklarovat a nechat uživatele metody, aby se s tímto problémem vypořádali sami:

Public void writeList() vyvolá IOException ( //teď nemusíme vyřizovat výjimku sami.}

Zpracovat nebo prohlásit?

Kdy bychom měli zpracovávat výjimky a kdy bychom je měli deklarovat? Velmi jednoduchá otázka... škoda, že na ni neexistuje jednoznačná odpověď. Obecně je třeba dodržovat následující pravidla:

Zpracujte výjimku, když můžete; vyhlásit výjimku, když tak musíte udělat.

Co z toho vyplývá? Obecně platí, že metoda by měla předat výjimku volajícímu pouze v případě, že sama nemá dostatečné informace ke zpracování výjimky.

Výhody, které nám používání výjimek poskytuje

napište sem o chybových kódech a rozbalte seznam

  1. Oddělení normálního kódu a kódu pro zpracování chyb
  2. Schopnost předávat výjimky pro zpracování zásobníku volání
  3. Seskupování a zpracování chyb podle typu

Problémy se zpracováním výjimek

"Ztracené výjimky"

Obecně jsou výjimky v Javě velmi pohodlné a jednoduché, ale bohužel mají také nevýhodu. Přestože výjimky jsou indikátory problémů v programu a neměly by být ignorovány, je možné, že se výjimka jednoduše ztratí. To se může stát, pokud kód do bloku final napíšeme špatně. Podívejme se na jednoduchý příklad:

// Jak lze vyvolat výjimku. class VeryImportantException rozšiřuje výjimku ( public String toString () ( return " Velmi důležitá výjimka!" ; ) ) class HoHumException rozšiřuje výjimku ( public String toString () ( return " Triviální výjimka " ; ) ) public class LostMessage ( void f () vyvolá VeryImportantException ( throw new VeryImportantException () ; ) void cancel () vyvolá HoHumException ( vyvolá novou HoHumException () ; ) public static void main ( String args ) vyvolá výjimku ( LostMessage lm = new LostMessage () ; try ( lm . f () ;) konečně (lm. zlikvidovat ();))

Co získáme jako výsledek spuštění tohoto kódu?

Výjimka ve vlákně "main" Triviální výjimka
na LostMessage.dispose(LostMessage.java:21)
na LostMessage.main(LostMessage.java:29)

Ach hrůza, přišli jsme o VeryImportantException, která pro nás byla velmi důležitá, a místo toho jsme dostali méně významnou.
Proto při psaní kódu do bloku final musíte být velmi opatrní, aby k takové ztrátě informací nedošlo.




Nahoru