1. Undtagelser

>

Langt om længe tænkte programmører på at standardisere og automatisere fejlhåndtering. Dette skete, da undtagelserne blev opfundet. Nu håndterer undtagelsesmekanismen 80 % af de ekstraordinære situationer.

Hvis en forsker fandt på undtagelser, var det sandsynligvis emnet for hans eller hendes doktorafhandling. Hvis en programmør fandt på det, så har han måske fået et venligt skulderklap fra en kollega: "Det virker okay, bro."

Når der opstår en fejl i et Java-program, såsom division med 0, sker der nogle vidunderlige ting:

Trin et

Der oprettes et særligt undtagelsesobjekt, som indeholder information om den opståede fejl.

Alt i Java er et objekt, og undtagelser er ingen undtagelser 🙂 Undtagelsesobjekter har deres egne klasser, og det eneste der adskiller dem fra almindelige klasser er, at de arver klassen Throwable.

Trin to

Undtagelsesobjektet er "smidt". Måske kunne formuleringen her være bedre. "At kaste en undtagelse" er mere som at udløse en brandalarm eller afgive en "DEFCON 1"-alarm.

Når der kastes en undtagelse til Java-maskinen, stopper den normale drift af programmet, og "nødprotokoller" begynder.

Trin tre

Metoden, hvor undtagelsen blev kastet, afsluttes med det samme. Undtagelsen overføres til opkaldsmetoden, som også afsluttes med det samme. Og så videre ned ad kæden, indtil mainmetoden afsluttes. Når mainmetoden afsluttes, gør programmet det også.

Eksempel:

Kode Konsoludgang
class Solution
{
   public static void main(String[] args)
   {
      System.out.println("Your attention, please! Preparing for the end of the world");
      endTheWorld();
      System.out.println("The world ended successfully");
   }

   public static void endTheWorld()
   {
      System.out.println("We're doing something important");
      doSomeWork(0);
      System.out.println("Everything is working well");
   }

   public static void doSomeWork(int n)
   {
      System.out.println("Nothing terrible will happen: " + n);
      System.out.println(2 / n);
      System.out.println("Nothing terrible happened: " + n);
   }
}
Your attention, please! Preparing for the end of the world
We're doing something important
Nothing terrible will happen: 0

En undtagelse opstår på linje 20: division med 0. Java-maskinen opretter straks en undtagelse — et ArithmeticExceptionobjekt og "smider" det til metoden.

Metoden divide()slutter med det samme, så vi ser aldrig strengen: Der skete ikke noget forfærdeligt: ​​0. Programmet vender tilbage til metoden endTheWorld(), og situationen gentager sig: der er en uhåndteret undtagelse i systemet, hvilket betyder, at metoden endTheWorld()også afsluttes unormalt. Derefter mainafsluttes metoden, og programmet stopper.

Hvad er formålet med disse undtagelser? Nå, du kan skrive din egen kode for at fange bestemte typer undtagelser og skrive din egen logik til at håndtere exceptionelle situationer.


2. Fangeundtagelser:try-catch

Java har en undtagelsesfangstmekanisme, der lader dig stoppe denne unormale afslutning af metoder. Det ser sådan ud:

try
{
   // Code where an exception might occur
}
catch(ExceptionType name)
{
   // Exception handling code
}

Denne konstruktion kaldes en try-catchblok.

Koden, hvor der kan forekomme undtagelser , er pakket ind i krøllede klammeparenteser efter ordet try.

Efter de krøllede klammeparenteser har vi nøgleordet catchog inden for parentes erklæringen af ​​en undtagelsesvariabel . Dette efterfølges af krøllede klammeparenteser, der ombryder koden, der skal udføres, hvis der opstår en undtagelse af den angivne type .

Hvis der ikke kastes undtagelser under udførelse af den " primære kode ", vil koden inde i catch-blokken ikke blive eksekveret. Hvis der opstår en undtagelse, så vil den være det (hvis typen af ​​den kastede undtagelse er den samme som typen af ​​variablen i parentes).

Eksempel:

Kode Konsoludgang
class Solution
{
   public static void main(String[] args)
   {
      System.out.println("Hadron Collider launched");

      try
      {
         launchHadronCollider(1);
         launchHadronCollider(0);
      }
      catch(Exception e)
      {
         System.out.println("Error! Caught an exception");
         System.out.println("The planet was sucked into a black hole!");
      }

      System.out.println("The Hadron Collider stopped");
   }

   public static void launchHadronCollider(int n)
   {
      System.out.println("Everything is working well: " + n);
      System.out.println(2/n);
      System.out.println("There are no problems: " + n);
   }
}
Hadron Collider launched
Everything is working fine: 1
2
There are no problems: 1
Everything is working fine: 0
Error! Caught an exception
The planet has been sucked into a black hole!
The Hadron Collider is stopped


3. Flere catchblokke

Flere fangblokke

I teorien kan alle mulige undtagelser smides i en kodeblok. Nogle vil du gerne håndtere på den ene måde, andre på en anden måde, og atter andre vil du beslutte dig for slet ikke at håndtere.

Java-udviklere besluttede at hjælpe dig og lade dig skrive ikke én, men mange catchblokke efter tryblokeringen.

try
{
   // Code where an exception might occur
}
catch (ExceptionType1 name1)
{
   // Code for handling ExceptionType1
}
catch (ExceptionType2 name2)
{
   // Code for handling ExceptionType2
}
   catch (ExceptionType3 name3)
{
   // Code for handling ExceptionType3
}

Eksempel:

Kode Konsoludgang
class Solution
{
   public static void main(String[] args)
   {
      System.out.println("Start of main method");
      try
      {
         calculate(0);
      }
      catch (ArithmeticException e)
      {
         System.out.println("Division by 0");
      }
      catch(Exception e)
      {
         System.out.println("Caught some kind of exception");
      }

      System.out.println("End of main method");
   }

   public static void calculate(int n)
   {
      System.out.println("Start of calculate method: " + n);
      System.out.println(2/n);
      System.out.println("End of calculate method: " + n);
   }
}
Start of main method
Start of calculate method: 0
Division by 0
End of main method


4. Rækkefølge af catchblokke

Undtagelser, der forekommer i en tryblok, kan kun fanges af en enkelt catchblok. Du kan ikke have en undtagelseshåndteringssituation, hvor koden fra flere catchblokke bliver eksekveret.

Men rækkefølgen af ​​blokkene har betydning.

Du kan have en situation, hvor en undtagelse kan blive fanget af flere blokke. Hvis det er tilfældet, vil undtagelsen blive fanget af den catch- blok, der kommer først (tættest på tryblokken).

Hvordan kan du have en situation, hvor flere catch-blokke kan fange den samme undtagelse?

Alle undtagelser tilhører et enkelt arvehierarki - se diagrammet.

Undtagelseshierarki

Et ArithmeticExceptionobjekt kan tildeles til en variabel, hvis type er ArithmeticExceptioneller en af ​​dens forfaderklasser: RuntimeException , Exceptionog Throwable— se diagrammet.

Vi vil tale mere om arv og forfædreklasser på niveau 21.

Denne kode vil kompilere fint:

Fordele ved arv:
ArithmeticException ae    = new ArithmeticException();
RuntimeException runtime  = new ArithmeticException();
Exception exception       = new ArithmeticException();
Throwable trwbl           = new ArithmeticException();

Så du kan fange en ArithmeticExceptionmed enhver af de 4 catchblokke ovenfor.

Eksempel 1:

Kode Konsoludgang
class Solution
{
   public static void main(String[] args)
   {
      System.out.println("Start of main method");
      try
      {
         calculate(0);
      }
      catch(ArithmeticException e)
      {
         System.out.println("Division by 0");
      }
      catch(Exception e)
      {
         System.out.println("Caught some kind of exception");
      }

      System.out.println("End of main method");
   }

   public static void calculate(int n)
   {
      System.out.println("Start of calculate method: " + n);
      System.out.println(2/n);
      System.out.println("End of calculate method: " + n);
   }
}
Start of main method
Start of calculate method: 0
Division by 0
End of main method

I dette eksempel ArithmeticExceptionkan den fanges af både blokkene catch (Exception e)og catch (ArithmeticException e). Det vil blive fanget af blokken tættest på blokken try- den første catchblok.

For at undgå overraskelser er det bedst at placere catchblokke, der kan fange næsten enhver undtagelse nær slutningen af ​​listen over catchblokke.

Typen Throwableer generelt i stand til at fange enhver mulig undtagelse i Java . Hvis du sætter den i den første catchblok, så kompilerer koden ikke, da compileren ved, at der er kodeblokke, der ikke kan nås.