1. Undantag

>

Äntligen tänkte programmerare att standardisera och automatisera felhantering. Detta hände när undantag uppfanns. Nu hanterar undantagsmekanismen 80 % av exceptionella situationer.

Om någon forskare kom med undantag var det troligen ämnet för hans eller hennes doktorsavhandling. Om en programmerare kom på det, så kan han ha fått en vänlig klapp på axeln från en kollega: "Det verkar okej, bro."

När ett fel uppstår i ett Java-program, till exempel division med , 0händer några underbara saker:

Steg ett

Ett speciellt undantagsobjekt skapas som innehåller information om felet som uppstod.

Allt i Java är ett objekt, och undantag är inga undantag 🙂 Undantagsobjekt har sina egna klasser, och det enda som skiljer dem från vanliga klasser är att de ärver klassen Throwable.

Steg två

Undantagsobjektet är "kastat". Kanske kan formuleringen här vara bättre. "Att kasta ett undantag" är mer som att utlösa ett brandlarm eller ljuda en "DEFCON 1"-larm.

När ett undantag kastas till Java-maskinen, stoppas den normala driften av programmet och "nödprotokoll" börjar.

Steg tre

Metoden där undantaget kastades avslutas omedelbart. Undantaget överförs till anropsmetoden, som också avslutas omedelbart. Och så vidare i kedjan tills mainmetoden går ut. När mainmetoden avslutas gör programmet det också.

Exempel:

Koda Konsolutgång
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

Ett undantag inträffar på rad 20: division med 0. Java-maskinen skapar omedelbart ett undantag — ett ArithmeticExceptionobjekt och "kastar" det till metoden.

Metoden divide()slutar omedelbart, så vi ser aldrig strängen: Inget hemskt hände: 0. Programmet återgår till metoden, endTheWorld()och situationen upprepar sig: det finns ett ohanterat undantag i systemet, vilket gör att metoden endTheWorld()också avslutas onormalt. Sedan mainavslutas metoden och programmet stoppas.

Vad är syftet med dessa undantag? Tja, du kan skriva din egen kod för att fånga vissa typer av undantag och skriva din egen logik för att hantera exceptionella situationer.


2. Fånga undantag:try-catch

Java har en undantagsfångningsmekanism som låter dig stoppa denna onormala avslutning av metoder. Det ser ut så här:

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

Denna konstruktion kallas ett try-catchblock.

Koden där undantag kan förekomma är inlindad i hängslen, föregås av ordet try.

Efter de lockiga klammerparenteserna har vi catchnyckelordet och, inom parentes, deklarationen av en undantagsvariabel . Detta följs av klammerparenteser som omsluter koden som ska köras om ett undantag av den angivna typen inträffar .

Om inga undantag slängs under exekvering av den " primära koden ", kommer koden inuti fångstblocket inte att exekveras. Om ett undantag inträffar, kommer det att vara det (om typen av det kastade undantaget är samma som typen av variabeln inom parentes).

Exempel:

Koda Konsolutgång
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. Flera catchblock

Flera fångstblock

I teorin kan alla möjliga undantag kastas i ett kodblock. Vissa kommer du att vilja hantera på ett sätt, andra på ett annat sätt, och andra kommer du att bestämma dig för att inte hantera alls.

Java-utvecklare bestämde sig för att hjälpa dig och låta dig skriva inte ett utan många catchblock efter tryblocket.

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
}

Exempel:

Koda Konsolutgång
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. Ordning av catchblock

Undantag som förekommer i ett tryblock kan bara fångas upp av ett enda catchblock. Du kan inte ha en undantagshanteringssituation där koden från flera catchblock exekveras.

Men ordningen på blocken spelar roll.

Du kan ha en situation där ett undantag kan fångas upp av flera block. Om så är fallet kommer undantaget att fångas upp av det fångstblock som kommer först (närmast blocket) try.

Hur kan du ha en situation där flera fångstblock kan fånga samma undantag?

Alla undantag hör till en enda arvshierarki — se diagrammet.

Undantagshierarki

Ett ArithmeticExceptionobjekt kan tilldelas en variabel vars typ är ArithmeticExceptioneller någon av dess förfaderklasser: , RuntimeException och ExceptionThrowablese diagrammet.

Vi kommer att prata mer om arv och förfaderklasser på nivå 21.

Den här koden kommer att kompileras bra:

Fördelar med arv:
ArithmeticException ae    = new ArithmeticException();
RuntimeException runtime  = new ArithmeticException();
Exception exception       = new ArithmeticException();
Throwable trwbl           = new ArithmeticException();

Så du kan fånga en ArithmeticExceptionmed något av de 4 catchblocken ovan.

Exempel 1:

Koda Konsolutgång
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 det här exemplet ArithmeticExceptionkan den fångas av både blocken catch (Exception e)och . catch (ArithmeticException e)Det kommer att fångas av blocket närmast blocket try- det första catchblocket.

För att undvika överraskningar är det bäst att placera catchblock som kan fånga nästan alla undantag nära slutet av listan med catchblock.

Typen Throwableär i allmänhet kapabel att fånga alla möjliga undantag i Java . Om du lägger den i det första catchblocket kommer koden inte att kompileras, eftersom kompilatorn vet att det finns oåtkomliga kodblock.