1. Unntak

>

Endelig tenkte programmerere å standardisere og automatisere feilhåndtering. Dette skjedde da unntak ble oppfunnet. Nå håndterer unntaksmekanismen 80 % av eksepsjonelle situasjoner.

Hvis noen forskere kom med unntak, var det sannsynligvis temaet for doktoravhandlingen hans eller hennes. Hvis en programmerer kom på det, så kan han ha fått et vennlig klapp på skulderen fra en kollega: "Ser greit ut, bro."

Når det oppstår en feil i et Java-program, for eksempel divisjon med 0, skjer det noen fantastiske ting:

Steg en

Det opprettes et spesielt unntaksobjekt som inneholder informasjon om feilen som oppstod.

Alt i Java er et objekt, og unntak er ingen unntak 🙂 Unntaksobjekter har sine egne klasser, og det eneste som skiller dem fra vanlige klasser er at de arver klassen Throwable.

Trinn to

Unntaksobjektet er "kastet". Kanskje ordlyden her kunne vært bedre. «Å kaste et unntak» er mer som å utløse en brannalarm eller gi et «DEFCON 1»-varsel.

Når et unntak blir kastet til Java-maskinen, stopper normal drift av programmet og "nødprotokoller" begynner.

Trinn tre

Metoden der unntaket ble kastet, avsluttes umiddelbart. Unntaket overføres til anropsmetoden, som også avsluttes umiddelbart. Og så videre nedover kjeden til mainmetoden går ut. Når mainmetoden avsluttes, gjør programmet det også.

Eksempel:

Kode Konsollutgang
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

Et unntak oppstår på linje 20: divisjon med 0. Java-maskinen oppretter umiddelbart et unntak — et ArithmeticExceptionobjekt og "kaster" det til metoden.

Metoden divide()avsluttes umiddelbart, så vi ser aldri strengen: Ingenting forferdelig skjedde: 0. Programmet går tilbake til metoden endTheWorld(), og situasjonen gjentar seg: det er et ubehandlet unntak i systemet, som gjør at metoden endTheWorld()også avsluttes unormalt. Deretter mainavsluttes metoden, og programmet stopper.

Hva er hensikten med disse unntakene? Vel, du kan skrive din egen kode for å fange opp spesielle typer unntak og skrive din egen logikk for å håndtere eksepsjonelle situasjoner.


2. Fange-unntak:try-catch

Java har en unntaksfangstmekanisme som lar deg stoppe denne unormale avslutningen av metoder. Det ser slik ut:

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

Denne konstruksjonen kalles en try-catchblokk.

Koden der unntak kan forekomme er pakket inn i krøllete klammeparenteser, foran ordet try.

Etter de krøllete klammeparentesene har vi nøkkelordet catchog, innenfor parentes, deklarasjonen av en unntaksvariabel . Dette etterfølges av krøllete klammeparenteser som omslutter koden som skal kjøres hvis et unntak av den angitte typen inntreffer .

Hvis ingen unntak blir kastet under kjøring av " primærkoden ", vil ikke koden inne i catch-blokken bli utført. Hvis et unntak oppstår, vil det være det (hvis typen av det kastede unntaket er den samme som typen til variabelen i parentes).

Eksempel:

Kode Konsollutgang
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 catchblokker

Flere fangstblokker

I teorien kan alle slags unntak kastes i en kodeblokk. Noen vil du ønske å håndtere på en måte, andre på en annen måte, og atter andre vil du bestemme deg for ikke å håndtere i det hele tatt.

Java-utviklere bestemte seg for å hjelpe deg og la deg skrive ikke én, men mange catchblokker etter tryblokkeringen.

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 Konsollutgang
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. Rekkefølge av catchblokker

Unntak som forekommer i en tryblokk kan bare fanges opp av en enkelt catchblokk. Du kan ikke ha en unntakshåndteringssituasjon der koden fra flere catchblokker blir utført.

Men rekkefølgen på blokkene betyr noe.

Du kan ha en situasjon der et unntak kan bli fanget opp av flere blokker. Hvis det er tilfelle, vil unntaket bli fanget opp av den fangblokken som kommer først (nærmest tryblokken).

Hvordan kan du ha en situasjon der flere fangstblokker kan fange det samme unntaket?

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

Unntakshierarki

Et ArithmeticExceptionobjekt kan tilordnes til en variabel hvis type er ArithmeticExceptioneller en av dens stamfarklasser: RuntimeException , Exceptionog Throwable— se diagrammet.

Vi snakker mer om arv og forfedreklasser på nivå 21.

Denne koden vil kompilere helt fint:

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

Så du kan fange en ArithmeticExceptionmed hvilken som helst av de 4 catchblokkene ovenfor.

Eksempel 1:

Kode Konsollutgang
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 eksemplet ArithmeticExceptionkan den fanges opp av både blokkene catch (Exception e)og catch (ArithmeticException e). Den vil bli fanget opp av blokken nærmest blokken try- den første catchblokken.

For å unngå overraskelser, er det best å plassere catchblokker som kan fange nesten alle unntak nær slutten av listen over catchblokker.

Typen Throwableer generelt i stand til å fange opp alle mulige unntak i Java . Hvis du legger den i den første catchblokken, vil ikke koden kompilere, siden kompilatoren vet at det er uoppnåelige kodeblokker.