"Hej, Amigo. Vi ska ha en mycket intressant lektion idag. Jag ska berätta om undantag. Undantag är en speciell mekanism som låter oss hantera fel i programmet. Här är några exempel på fel som kan uppstå i ett program:

1. Programmet kan försöka skriva en fil när hårddisken är helt full.

2. Programmet kan försöka anropa en metod på en variabel som lagrar en nollreferens.

3. Programmet kan försöka dividera ett tal med 0."

Alla dessa åtgärder resulterar i fel. Vanligtvis blir resultatet att programmet avslutas omedelbart, eftersom det inte är meningsfullt att fortsätta exekvera kod i detta fall.

"Varför?"

"Är det vettigt att fortsätta svänga ett hjul om bilen har åkt av vägen och faller från en klippa?"

"Ska programmet sluta köra då?"

"Ja. Åtminstone, detta är vad som brukade hända. Alla fel gjorde att programmet avslutades."

"Det är ett väldigt smart tillvägagångssätt."

"Men vore det inte bättre att försöka fortsätta köra programmet?"

"Ja. Anta att du skrev en enorm mängd text i Word och sparade den. Tänk om sparaoperationen misslyckas, men programmet får dig att tro att allt är bra? Och du fortsätter att skriva. Det vore dumt, inte Det?"

"Japp."

"Sedan kom programmerare på en intressant lösning: varje funktion skulle returnera status för sitt arbete. 0 betydde att den fungerade som förväntat. Alla andra värden skulle betyda att något fel uppstod, och returvärdet var en felkod."

"Men det tillvägagångssättet har också sina brister. Efter varje (!) funktionsanrop måste du kontrollera returkoden (numret). Först och främst är detta obekvämt: felhanteringskoden exekveras sällan utan måste inkluderas överallt. För det andra returnerar funktioner ofta olika värden – vad ska du göra med dem?"

"Okej. Jag tänkte på det också."

"Sedan kom en ljus framtid i form av undantag och en felhanteringsmekanism. Så här fungerar det:

1. När ett fel uppstår skapar Java Machine ett speciellt objekt – ett undantag – där den sparar all felinformation. Det finns olika undantag för olika fel.

2. Ett undantag gör att programmet omedelbart avslutar den aktuella funktionen, och nästa funktion, och så vidare – tills det avslutar huvudmetoden. Sedan avslutas programmet. Programmerare kan också säga att Java-maskinen "lindar upp samtalsstacken".

"Men du sa att programmet inte alltid avslutas."

"Ja, för det finns ett sätt att fånga ett undantag. Vi kan skriva specialkod på rätt plats för att fånga upp de undantag vi bryr oss om och göra något med dem. Det här är viktiga grejer."

"För att hjälpa oss att göra detta finns det en speciell try-catch- konstruktion. Så här fungerar det:"

Exempel på ett program som fångar ett undantag (division med 0) och fortsätter att fungera.
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);
    }
}
Skärmutgång:

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

"Men varför kommer inte 'Efter anropsmetod1. Detta kommer aldrig att visas' att visas på skärmen?"

"Jag är glad att du frågade. På rad 25 dividerar vi med 0, vilket leder till ett fel – ett undantag. Java-maskinen skapar ett ArithmeticException -objekt med information om felet. Objektet är undantaget."

"Undantaget förekommer inuti method1metoden. Detta gör att metoden avslutas omedelbart. Det skulle få huvudmetoden att avslutas om inte försöksfångsblocket ."

"Om ett undantag inträffar i ett försöksblock , fångas det i catch -blocket. Resten av koden i försöksblocket kommer inte att exekveras. Istället kommer catch- blocket att börja exekveras. "

"Jag fattar inte."

"Med andra ord fungerar koden så här:

1. Om ett undantag inträffar i ett försöksblock , slutar koden att exekveras där undantaget inträffade och catch -blocket börjar exekveras.

2. Om inget undantag inträffar exekveras försöksblocket till slutet och fångstblocket exekveras inte. "

"Va?"

"Föreställ dig att vi efter varje metodanrop kontrollerar om metoden returnerade normalt eller abrupt avslutades som ett resultat av ett undantag. Om det finns ett undantag, så går vi till exekvera catch-blocket (om det finns ett) för att fånga undantaget. Om det inte finns något fångstblock, avslutar vi den nuvarande metoden, och metoden som anropade oss utför samma kontroll."

"Jag tror att jag har fattat det nu."

"Excellent."

"Vad betyder "Undantag" i fångstförklaringen?"

" Alla undantag är klasser som ärver Exception-klassen. Vi kan fånga ett visst undantag genom att ange undantagsklassen i catch- blocket, eller så kan vi fånga alla undantag genom att ange deras gemensamma överordnade klass – Exception. Då kan vi få alla nödvändiga fel information från variabeln e (den lagrar en referens till undantagsobjektet)."

"Cool! Om olika undantag förekommer i min metod, kan jag då behandla dem annorlunda?"

"Inte bara kan du, men du borde. Du kan göra det så här:"

Exempel:
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);
    }
}

"Försöksblocket kan paras ihop med flera fångstblock , som vart och ett kommer att fånga de angivna typerna av undantag. "

"Jag tror att jag förstår. Jag kan inte skriva det här själv än, men om jag stöter på det i kod blir jag inte rädd."