1. Excepții

>

În cele din urmă, programatorii s-au gândit să standardizeze și să automatizeze gestionarea erorilor. Acest lucru s-a întâmplat când au fost inventate excepții . Acum mecanismul de excepție gestionează 80% din situațiile excepționale.

Dacă un savant a venit cu excepții, probabil că a fost subiectul tezei sale de doctorat. Dacă un programator a venit cu asta, atunci poate că a primit o palmă prietenoasă pe spate de la un coleg: „Se pare în regulă, frate”.

Când apare o eroare într-un program Java, cum ar fi împărțirea cu 0, se întâmplă câteva lucruri minunate:

Primul pas

Este creat un obiect excepție special, care conține informații despre eroarea care a apărut.

Totul în Java este un obiect, iar excepțiile nu sunt excepții 🙂 Obiectele excepție au propriile lor clase și singurul lucru care le diferențiază de clasele obișnuite este că moștenesc clasa Throwable.

Pasul doi

Obiectul excepție este „aruncat”. Poate că formularea de aici ar putea fi mai bună. „Aruncarea unei excepții” este mai degrabă ca declanșarea unei alarme de incendiu sau sunetul unei alerte „DEFCON 1”.

Când o excepție este aruncată la mașina Java, funcționarea normală a programului se oprește și încep „protocoalele de urgență”.

Pasul trei

Metoda în care a fost aruncată excepția iese imediat. Excepția este transmisă metodei de apelare, care, de asemenea, iese imediat. Și așa mai departe în lanț până când mainmetoda iese. Când mainmetoda se termină, la fel și programul.

Exemplu:

Cod Ieșire de consolă
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

O excepție apare pe linia 20: împărțirea cu 0. Mașina Java creează imediat o excepție - un ArithmeticExceptionobiect și îl „aruncă” metodei.

Metoda divide()se termină imediat, așa că nu vedem niciodată șirul: Nu s-a întâmplat nimic groaznic: 0. Programul revine la metodă endTheWorld(), iar situația se repetă: există o excepție netratată în sistem, ceea ce înseamnă că endTheWorld()și metoda se termină anormal. Apoi mainmetoda se termină, iar programul se oprește.

Care este scopul acestor excepții? Ei bine, puteți scrie propriul cod pentru a prinde anumite tipuri de excepții și vă puteți scrie propria logică pentru a gestiona situații excepționale.


2. Obțineți excepții:try-catch

Java are un mecanism de captare a excepțiilor care vă permite să opriți această terminare anormală a metodelor. Arata cam asa:

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

Acest construct se numește try-catchbloc.

Codul în care pot apărea excepții este înfășurat în acolade, precedat de cuvântul try.

După acolade, avem cuvântul catchcheie și, între paranteze, declarația unei variabile de excepție . Aceasta este urmată de acolade care încapsulează codul care urmează să fie executat dacă apare o excepție de tipul specificat .

Dacă nu sunt aruncate excepții în timpul execuției „ codului primar ”, atunci codul din interiorul blocului catch nu va fi executat. Dacă apare o excepție, atunci va fi (dacă tipul excepției aruncate este același cu tipul variabilei din paranteze).

Exemplu:

Cod Ieșire de consolă
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. catchBlocuri multiple

Blocuri de prindere multiple

În teorie, într-un bloc de cod pot fi aruncate tot felul de excepții. Unele veți dori să vă descurcați într-un fel, altele într-un alt fel, iar altele veți decide să nu le gestionați deloc.

Dezvoltatorii Java au decis să vă ajute și să vă permită să scrieți nu unul, ci multe catchblocuri după trybloc.

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
}

Exemplu:

Cod Ieșire de consolă
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. Ordinea catchblocurilor

Excepțiile care apar într-un trybloc pot fi capturate doar de un singur catchbloc. Nu puteți avea o situație de gestionare a excepțiilor în care codul din mai multe catchblocuri este executat.

Dar ordinea blocurilor contează.

Puteți avea o situație în care o excepție ar putea fi prinsă de mai multe blocuri. Dacă acesta este cazul, atunci excepția va fi prinsă de oricare bloc de capturătry care vine primul (cel mai aproape de bloc).

Cum poți avea o situație în care mai multe blocuri de captură pot prinde aceeași excepție?

Toate excepțiile aparțin unei singure ierarhii de moștenire - vezi diagrama.

Ierarhia excepțiilor

Un ArithmeticExceptionobiect poate fi atribuit unei variabile al cărei tip este ArithmeticExceptionsau oricare dintre clasele sale strămoși: RuntimeException și ExceptionThrowablevezi diagrama.

Vom vorbi mai multe despre moștenire și clase de strămoși la nivelul 21.

Acest cod se va compila foarte bine:

Beneficiile moștenirii:
ArithmeticException ae    = new ArithmeticException();
RuntimeException runtime  = new ArithmeticException();
Exception exception       = new ArithmeticException();
Throwable trwbl           = new ArithmeticException();

Deci, puteți prinde un ArithmeticExceptioncu oricare dintre cele 4 catchblocuri de mai sus.

Exemplul 1:

Cod Ieșire de consolă
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

În acest exemplu, ArithmeticExceptionpoate fi prins atât de blocuri catch (Exception e)cât și catch (ArithmeticException e). Va fi prins de blocul cel mai apropiat de trybloc — primul catchbloc.

Pentru a evita surprizele, cel mai bine este să plasați catchblocuri care pot prinde aproape orice excepție aproape de sfârșitul listei de catchblocuri.

Tipul Throwableeste, în general, capabil să prindă orice excepție posibilă în Java . Dacă îl puneți în primul catchbloc, atunci codul nu se va compila, deoarece compilatorul știe că există blocuri de cod inaccesibile.