1. Wyjątki

Wyjątki w programach Java

Wreszcie programiści pomyśleli o regulacji i automatyzacji obsługi błędów. Stało się tak, gdy wymyślono wyjątki . Teraz za pomocą mechanizmu wyjątków na świecie przetwarza się 80% sytuacji awaryjnych.

Jeśli jakiś naukowiec wymyślił wyjątki, to najprawdopodobniej obronił na ten temat swoją rozprawę doktorską. Jeśli programista to wymyślił, być może otrzymał przyjacielskie poklepanie po ramieniu od kolegów: „Wydaje się, że to normalne, bracie”.

Gdy w programie Java wystąpi błąd, taki jak dzielenie przez 0, dzieją się cudowne rzeczy:

Krok pierwszy

Tworzony jest specjalny obiekt wyjątku, który zawiera informacje o wystąpieniu błędu.

Wszystko w Javie jest obiektem, a wyjątki nie są wyjątkiem 🙂 Obiekty wyjątków mają swoje własne klasy, a od zwykłych klas różnią się tylko tym, że są dziedziczone z klasy Throwable.

krok drugi

Obiekt wyjątku jest „rzucany”. Niezbyt dobre imię. „Zgłaszanie wyjątku” jest w istocie bardziej jak aktywacja alarmu przeciwpożarowego lub ostrzeganie cię za pomocą „alarmu bojowego”.

W momencie „wrzucenia” do systemu wyjątku normalne działanie programu zostaje zakończone, a rozpoczyna się „praca według protokołu awaryjnego”.

Krok trzeci

Bieżąca metoda, która napotkała (zgłosiła) wyjątek, kończy się natychmiast. Wyjątek jest przekazywany do metody wywołującej, która również kończy się natychmiast.  I tak dalej w łańcuchu, aż metoda się skończy main. Gdy metoda się kończy, mainprogram również się kończy.

Przykład:

Kod Wyjście na wyświetlaczu
class Solution
{
   public static void main(String[] args)
   {
      System.out.println("Внимание! Подготовка к концу света");
      конецСвета();
      System.out.println("Конец света успешно завершён");
   }

   public static void конецСвета()
   {
      System.out.println("Czyn что-то важное");
      поделим(0);
      System.out.println("Все отлично работает");
   }

   public static void поделим(int n)
   {
      System.out.println("Ничего страшного не произойдет: " + n);
      System.out.println(2 / n);
      System.out.println("Ничего страшного не произошло: " + n);
   }
}
Внимание! Подготовка к концу света
Czyn что-то важное
Ничего страшного не произойдет: 0

Wystąpił błąd w linii 20 - dzielenie przez 0 . Maszyna Java natychmiast stworzyła wyjątek - obiekt klasy ArithmeticExceptioni "wrzuciła" go do systemu.

Metoda поделим() zakończyła się natychmiast, więc linia nie pojawiła się na ekranie Nic strasznego się nie stało: 0. Program wrócił do metody конецСвета()i sytuacja się powtórzyła: w systemie jest wyjątek, co oznacza, że ​​​​metoda конецСвета() również się zawiesza . Następnie metoda zostaje zakończona main, a wykonywanie programu zostaje zatrzymane.

Jaki jest cel takich wyjątków? I fakt, że w swoim programie możesz przechwytywać wyjątki określonego typu i pisać własną logikę obsługi sytuacji awaryjnych.


2. Łapanie wyjątkówtry-catch

Java ma mechanizm przechwytywania wyjątków, który pozwala zapobiegać awariom metod. To wygląda tak:

try
{
   kod, где может возникнуть ошибка
}
catch(ТипИсключения Nazwa)
{
   kod обработки исключения
}

Ten projekt nazywa się blokiem try-catch.

Kod wyjątku jest ujęty w nawiasy klamrowe poprzedzone słowem try(try).

Po nawiasach klamrowych zapisywane jest słowo kluczowe catch, wewnątrz nawiasów deklarowana jest zmienna typu wyjątku . Po nim następują nawiasy klamrowe, wewnątrz których zapisany jest kod, który ma zostać wykonany w przypadku wystąpienia wyjątku określonego typu.

Jeśli podczas wykonywania „ kodu głównego ” nie zostały zgłoszone żadne wyjątki , kod wewnątrz bloku catch nie zostanie wykonany. Jeśli wystąpi wyjątek, tak się stanie (pod warunkiem, że typ wyjątku, który wystąpił, odpowiada typowi zmiennej w nawiasach).

Przykład:

Kod Wyjście na wyświetlaczu
class Solution
{
   public static void main(String[] args)
   {
      System.out.println("Адронный Коллайдер запущен");

      try
      {
         запуститьАдронныйКоллайдер(1);
         запуститьАдронныйКоллайдер(0);
      }
      catch(Exception e)
      {
         System.out.println("Ошибка! Перехвачено исключение");
         System.out.println("Планету засосало в черную дыру!");
      }

      System.out.println("Адронный Коллайдер остановлен");
   }

   public static void запуститьАдронныйКоллайдер(int n)
   {
      System.out.println("Все отлично работает: " + n);
      System.out.println(2/n);
      System.out.println("НиJakих проблем нет: " + n);
   }
}
Адронный Коллайдер запущен
Все отлично работает: 1
2
НиJakих проблем нет: 1
Все отлично работает: 0
Ошибка! Перехвачено исключение
Планету засосало в черную дыру!
Адронный Коллайдер остановлен


3. Wiele blokówcatch

Wiele bloków catch

Teoretycznie w bloku kodu mogą wystąpić różne wyjątki. Niektóre będziesz chciał przetwarzać w jeden sposób, inne w drugi, a jeszcze inne zdecydujesz się w ogóle nie przetwarzać.

Programiści Javy postanowili ci pomóc i pozwolili pisać po bloku trynie jeden blok catch, ale kilka.

try
{
   kod, где может возникнуть ошибка
}
catch(ТипИсключения1 Nazwa1)
{
   kod обработки исключения1
}
catch(ТипИсключения2 Nazwa2)
{
   kod обработки исключения2
}
   catch(ТипИсключения3 Nazwa3)
{
   kod обработки исключения3
}

Przykład:

Kod Wyjście na wyświetlaczu
class Solution
{
   public static void main(String[] args)
   {
      System.out.println("Начало метода main");
      try
      {
         calculate(0);
      }
      catch(ArithmeticException e)
      {
         System.out.println("Было деление на 0");
      }
      catch(Exception e)
      {
         System.out.println("Перехвачено Jakое-то исключение");
      }

      System.out.println("Конец метода main");
   }

   public static void calculate(int n)
   {
      System.out.println("calculate начало: " + n);
      System.out.println(2/n);
      System.out.println("calculate конец: " + n);
   }
}
Начало метода main
calculate начало: 0
Было деление на 0
Конец метода main


4. Zablokuj zamówieniecatch

Wyjątek zgłoszony w bloku trymoże zostać przechwycony tylko przez jeden blok catch. Nie może być sytuacji , że podczas obsługi wyjątku został wykonany kod z kilku bloków catch.

Jednak kolejność bloków ma znaczenie.

Może wystąpić sytuacja, w której wyjątek zostanie przechwycony przez wiele bloków. W takim przypadku zostanie przechwycony przez blok catch , który pojawi się wcześniej (bliżej bloku try).

Jak może dojść do sytuacji, w której jeden wyjątek może przechwycić kilka bloków catch?

Wszystkie wyjątki są łączone w jedną hierarchię za pomocą dziedziczenia — patrz diagram.

Hierarchia wyjątków Javy

Obiekt wyjątku typu ArithmeticExceptionmożna przypisać do zmiennej typu ArithmeticException, jak również do zmiennych jej klas przodków: RuntimeException , Exceptionoraz Throwable- patrz diagram.

Porozmawiamy więcej o dziedziczeniu i klasach przodków na poziomie 21.

Ten kod skompiluje się dobrze:

Korzyści z dziedziczenia:
ArithmeticException ae    = new ArithmeticException();
RuntimeException runtime  = new ArithmeticException();
Exception exception       = new ArithmeticException();
Throwable trwbl           = new ArithmeticException();

Dlatego możliwe jest przechwycenie wyjątku typu ArithmeticExceptionza pomocą bloków catchdowolnego z 4 typów podanych powyżej.

Przykład 1:

Kod Wyjście na wyświetlaczu
class Solution
{
   public static void main(String[] args)
   {
      System.out.println("Начало метода main");
      try
      {
         calculate(0);
      }
      catch(ArithmeticException e)
      {
         System.out.println("Было деление на 0");
      }
      catch(Exception e)
      {
         System.out.println("Перехвачено Jakое-то исключение");
      }

      System.out.println("Конец метода main");
   }

   public static void calculate(int n)
   {
      System.out.println("calculate начало: " + n);
      System.out.println(2/n);
      System.out.println("calculate конец: " + n);
   }
}
Начало метода main
calculate начало: 0
Было деление на 0
Конец метода main

W tym przykładzie wyjątek ArithmeticExceptionmoże zostać przechwycony zarówno przez blok, catch(Exception e)jak i przez blok catch(ArithmeticException e). Zostanie przechwycony przez blok, który jest najbliżej bloku try- pierwszy blok catch.

Aby uniknąć niespodzianek, najlepiej jest catchumieszczać bloki, które mogą przechwycić prawie wszystkie wyjątki, blisko końca listy bloków catch.

Typ Throwablejest generalnie zdolny do przechwytywania wszystkich możliwych wyjątków w Javie, jeśli zostanie umieszczony w pierwszym bloku catch- kod nie skompiluje się, ponieważ kompilator rozumie, że w kodzie znajdują się nieosiągalne bloki kodu.