"Szia, Amigo. Ma egy nagyon érdekes leckénk lesz. A kivételekről fogok beszélni. A kivételek egy speciális mechanizmus, amely lehetővé teszi számunkra a program hibáinak kezelését. Íme néhány példa az esetlegesen előforduló hibákra egy programban:

1. A program megpróbálhat fájlt írni, amikor a merevlemez teljesen megtelt.

2. A program megpróbálhat egy metódust meghívni egy null referenciát tároló változón.

3. A program megpróbálhat elosztani egy számot 0-val."

Mindezek a műveletek hibákhoz vezetnek. Általában az eredmény az, hogy a program azonnal leáll, mivel ebben az esetben nincs értelme folytatni a kód végrehajtását.

"Miért?"

– Van értelme tovább forgatni a kereket, ha az autó letért az útról és lezuhan egy szikláról?

"Akkor le kellene állnia a programnak?"

"Igen. Legalábbis ez történt. Bármilyen hiba miatt a program leállt."

– Ez egy nagyon okos megközelítés.

– De nem lenne jobb, ha megpróbálná folytatni a program futtatását?

"Igen. Tegyük fel, hogy hatalmas mennyiségű szöveget írt be a Wordbe, és elmentette. Mi van, ha a mentési művelet meghiúsul, de a program elhiteti veled, hogy minden rendben van? És folytatod a gépelést. Ez hülyeség lenne, nem azt?"

"Igen."

"Akkor a programozók egy érdekes megoldást találtak ki: minden függvény visszaadja a munkájának állapotát. A 0 azt jelentette, hogy a várt módon működik. Minden más érték azt jelenti, hogy valamilyen hiba történt, a visszatérési érték pedig egy hibakód."

"A megközelítésnek azonban vannak hiányosságai is. Minden (!) függvényhívás után ellenőrizni kell a visszatérési kódot (számot). Először is ez kényelmetlen: a hibakezelő kódot ritkán hajtják végre, de bele kell tenni Másodszor, a függvények gyakran különböző értékeket adnak vissza – mit kell velük csinálni?

– Helyes, ezen én is gondolkodtam.

"Ezután egy fényes jövő érkezett a kivételek és egy hibakezelési mechanizmus formájában. Így működik:

1. Hiba esetén a Java gép létrehoz egy speciális objektumot – kivételt –, ahol elmenti az összes hibainformációt. A különböző hibákhoz különböző kivételek vannak.

2. A kivétel hatására a program azonnal kilép az aktuális függvényből, majd a következő függvényből, és így tovább – amíg ki nem lép a fő metódusból. Ezután a program leáll. A programozók azt is mondhatják, hogy a Java gép „letekerteti a híváscsomagot”.

– De azt mondtad, hogy a program nem mindig fejeződik be.

"Igen, mert van mód a kivételek elkapására. Speciális kódot írhatunk a megfelelő helyre, hogy felfogjuk a számunkra fontos kivételeket, és tegyünk velük valamit. Ez fontos dolog."

"Segítségünkre van egy speciális try-catch konstrukció. Ez a következőképpen működik:

Példa egy olyan programra, amely elkap egy kivételt (osztás 0-val), és tovább dolgozik.
public class ExceptionExample2
{
    public static void main(String[] args)
    {
        System.out.println("Program starts");

        try
        {
            System.out.println("Before calling method1");
            method1();
            System.out.println("After calling method1. This will never be shown");
        }
        catch (Exception e)
        {
           System.out.println("Exception has been caught");
        }

        System.out.println("Program is still running");
    }

    public static void method1()
    {
        int a = 100;
        int b = 0;
        System.out.println(a / b);
    }
}
Képernyő kimenet:

Program starts
Before method1 calling
Exception has been caught
Program is still running

"De miért nem jelenik meg a képernyőn az "1. módszer hívása után. Ez soha nem fog megjelenni"?

"Örülök, hogy megkérdezte. A 25. sorban 0-val osztunk, ami hibához vezet – kivétel. A Java gép létrehoz egy ArithmeticException objektumot a hibával kapcsolatos információkkal. Az objektum a kivétel."

"A kivétel a method1metóduson belül történik. Ez a metódus azonnali leállását okozza. Ez a metódus leállását okozná , ha nem lenne a try-catch blokk."

"Ha kivétel történik egy try blokkon belül, akkor az elkapásra kerül a catch blokkban. A try blokkban lévő kód fennmaradó része nem kerül végrehajtásra. Ehelyett a catch blokk végrehajtása kezdődik meg. "

– Nem értem.

"Más szóval a kód így működik:

1. Ha kivétel történik egy try blokkon belül, a kód végrehajtása leáll ott, ahol a kivétel előfordult, és a catch blokk végrehajtása megkezdődik.

2. Ha nem történik kivétel, akkor a try blokk a végéig végrehajtásra kerül , a catch blokk pedig nem. "

– Huh?

"Képzeljük el, hogy minden metódushívás után ellenőrizzük, hogy a metódus normálisan tért-e vissza, vagy egy kivétel következtében hirtelen leállt. Ha van kivétel, akkor átlépünk a catch blokk végrehajtására (ha van), hogy elkapjuk a kivételt. Ha nincs fogási blokk, akkor leállítjuk az aktuális metódust, és a minket hívó metódus elvégzi ugyanazt az ellenőrzést."

– Azt hiszem, most megvan.

"Kiváló."

"Mit jelent a "kivétel" a catch utasításon belül?

" Minden kivétel olyan osztály, amely az Exception osztályt örökli. Egy adott kivételt elkaphatunk, ha megadjuk a kivételosztályt a catch blokkban, vagy az összes kivételt a közös szülőosztályuk megadásával – Kivétel. Ekkor megkapjuk az összes szükséges hibát. információ az e változóból (hivatkozást tárol a kivételobjektumra)."

"Jó! Ha eltérő kivételek fordulnak elő a módszeremben, akkor feldolgozhatom őket másképp?"

"Nemcsak megteheti, de meg is kell tennie. Ezt így teheti meg:"

Példa:
public class ExceptionExample2
{
    public static void main(String[] args)
    {
        System.out.println("Program starts");

        try
        {
            System.out.println("Before calling method1");
            method1();
            System.out.println("After calling method1. This will never be shown");
        }
        catch (NullPointerException e)
        {
           System.out.println("Null reference. Exception has been caught");
        }
        catch (ArithmeticException e)
        {
            System.out.println("Division by zero. Exception has been caught");
        }
        catch (Exception e)
        {
            System.out.println("Any other errors. Exception has been caught");
        }

        System.out.println("Program is still running");
    }

    public static void method1()
    {
        int a = 100;
        int b = 0;
        System.out.println(a / b);
    }
}

"A try blokk több fogási blokkkal párosítható , amelyek mindegyike elkapja a meghatározott típusú kivételeket."

"Azt hiszem, értem. Ezt magam még nem tudom megírni, de ha kódban találkozom vele, nem fogok megijedni."