"Błąd jest tylko sposobem na wyeliminowanie sposobów, które nie działają" - Thomas Edison
Jeśli to czytasz, to znaczy, że udało mi się przyciągnąć Twoją uwagę tym dość ekstrawaganckim tytułem 😉 Dobrze, że jesteś, bo temat, który wziałem na tapetę jest niezwykle istotny. Porozmawiamy o błędach w kodzie.
Oczywiście, Thomas Edison nie był programistą… Jednak właśnie w kontekście programowania, słowa tego cytatu nabierają szczególnego znaczenia. Podobnie jak w eksperymentach naukowych, gdzie błędy prowadzą do innowacji i odkryć, tak również podczas tworzenia oprogramownia błędy stanowią nieodłączną część tego procesu.
Dzięki błędom identyfikujemy potencjalne zagrożenia w kodzie. Właściwe zarządzanie błędami pozwala na budowanie stabilnych i niezawodnych rozwiązań poprzez eliminowanie nieskutecznych metod.
W Javie
, jak w każdym języku programowania, błędy są nieuniknione. Mogą być spowodowane przez wiele czynników - od błędów programistycznych po nieprzewidziane warunki środowiskowe. Jednak dzięki mechanizmowi obsługi wyjątków
, programiści mają potężne narzędzie do zarządzania tymi sytuacjami.
Wprowadzenie do wyjątków
Wyjątki Exceptions
są mechanizmem, który umożliwia programiście reagowanie na nieoczekiwane lub błędne warunki w programie. Mogą one być klasyfikowane jako "sprawdzane" checked
lub "niesprawdzane" unchecked
, w zależności od tego, czy są one weryfikowane podczas kompilacji.
Obsługa wyjątków
Obsługa wyjątków Exception handling
jest kluczowym elementem w tworzeniu solidnego i niezawodnego kodu. Dzięki niemu programista może zapewnić, że nawet w przypadku wystąpienia nieprzewidzianych zdarzeń, program zachowa kontrolę nad swoim działaniem i podejmie odpowiednie kroki, aby uniknąć katastrofy 💥
Techniki obsługi wyjątków
Poprawne i staranne zarządzanie wyjątkami może przyczynić się do zwiększenia czytelności, niezawodności i skalowalności kodu, a także ułatwić debugowanie oraz utrzymanie aplikacji w przyszłości. Istnieje kilka metod obsługi wyjątków.
Blok try-catch
Koncepcja, która pozwala na przechwytywanie i obsługę konkretnych typów wyjątków. W skrócie, kod wewnątrz bloku try
jest wykonywany, a jeśli wystąpi błąd, kontrola przechodzi do bloku catch
, gdzie można obsłużyć ten błąd.
Przykład 1:
Obsługa konkretnego wyjątku przy użyciu bloku try-catch
:
public class Example { public static void main(String[] args) { try { int[] numbers = {1, 2, 3}; System.out.println(numbers[4]); // próba dostępu do indeksu spoza zakresu tablicy } catch (ArrayIndexOutOfBoundsException e) { System.out.println("Wystąpił wyjątek: " + e.getMessage()); } } }
Przykład 2:
Użycie bloku try-catch
do obsługi wielu wyjątków:
public class Example { public static void main(String[] args) { try { int result = divide(10, 0); // próba dzielenia przez zero System.out.println("Wynik: " + result); } catch (ArithmeticException e) { System.out.println("Wystąpił wyjątek: " + e.getMessage()); } catch (Exception e) { System.out.println("Inny wyjątek: " + e.getMessage()); } } public static int divide(int a, int b) { return a / b; } }
Blok try-catch
polega na próbie wykonania kodu w bloku try
, gdzie może wystąpić wyjątek
. W przypadku pojawienia się wyjątku, kontrola przejdzie do odpowiedniego bloku catch
, który obsłuży ten wyjątek.
Blok finally
Zawiera fragment kodu, który zostanie wykonany niezależnie od tego, czy wystąpił wyjątek czy nie.
Przykład:
Użycie bloku try-catch-finally
:
import java.io.FileReader; import java.io.IOException; public class Example { public static void main(String[] args) { FileReader fileReader = null; try { fileReader = new FileReader("example.txt"); // Operacje na pliku } catch (IOException e) { System.out.println("Wystąpił błąd podczas operacji na pliku: " + e.getMessage()); } finally { try { if (fileReader != null) { fileReader.close(); } } catch (IOException e) { System.out.println("Nie udało się zamknąć pliku: " + e.getMessage()); } } } }
Po wykonaniu bloku catch
, program kontynuuje działanie. Kod w bloku finally
zostanie wykonany bez względu na to, czy wyjątek został zgłoszony czy nie. Blok finally
zapewnia, że pewne operacje zostaną zawsze wykonane po zakończeniu bloku try-catch
.
Klauzula throws
W języku Java, klauzula throws
jest używana, aby zadeklarować, jakie wyjątki może wyrzucić dana metoda, ale nie musi ich obsługiwać wewnątrz przy użyciu bloku try-catch
. Oznacza to, że jeśli wyjątek wystąpi wewnątrz tej metody, może ona przerwać swoje wykonanie i przekazać ten wyjątek wyżej do metody wywołującej. Metoda wywołująca musi wtedy albo obsłużyć ten wyjątek, albo również zadeklarować go w swojej klauzuli throws
.
import java.io.FileNotFoundException; import java.io.FileReader; public class Example { // Metoda readFromFile deklaruje, że może wyrzucić FileNotFoundException public static void readFromFile() throws FileNotFoundException { FileReader fileReader = new FileReader("plik.txt"); // ... } public static void main(String[] args) { try { readFromFile(); } catch (FileNotFoundException e) { System.out.println("Nie można znaleźć pliku: " + e.getMessage()); } } }
W tym przykładzie metoda readFromFile()
deklaruje, że może wyrzucić FileNotFoundException
, który może wystąpić, gdy próbuje się otworzyć plik, który nie istnieje. Metoda main()
wywołuje readFromFile()
i obsługuje ten wyjątek przy użyciu bloku try-catch
.
Typy wyjątków - Checked Exception
Sprawdzane wyjątki checked
, jak sama nazwa wskazuje, są sprawdzane przez kompilator. Metody, w których mogą wystąpić takie wyjątki, muszą entuzjastycznie je obsłużyć (try-catch
) lub zadeklarować, że zgłosić wystąpienie potencjalnego błedu w kodzie (throws
). Typowe przykłady obejmują np. operacje wejścia/wyjścia (I/O), takie jak czytanie/zapisywanie plików, czy operacje sieciowe.
try { FileReader file = new FileReader("plik.txt"); // kod, który operuje na pliku } catch (FileNotFoundException e) { // obsługa wyjątku FileNotFoundException }
⬅️ Przykłady
IOException
:
Jest to ogólny wyjątek związany z operacjami wejścia/wyjścia, takimi jak operacje na plikach
SQLException
:
Ten wyjątek występuje, gdy pojawi się problem z bazą danych
FileNotFoundException
:
Wyjątek ten występuje, gdy próba otwarcia pliku nie powiedzie się, np. kiedy plik o danej ścieżce nie istnieje
ParseException
:
Ten wyjątek jest rzucany, gdy wystąpi problem z parsowaniem danych
ClassNotFoundException
:
Występuje, gdy próba załadowania klasy nie powiedzie się, ponieważ klasa o podanej nazwie nie jest dostępna
Typy wyjątków - Unchecked Exception
Niesprawdzane wyjątki unchecked
, zwane także Runtime Exceptions
, nie są sprawdzane podczas kompilacji. Nie muszą być obsługiwane w bloku try-catch
oraz zgłaszane używając throws
. Te wyjątki zazwyczaj reprezentują błędy programistyczne lub sytuacje, które mogą wystąpić w trakcie działania programu i mogą być trudne do przewidzenia podczas kompilacji.
Wyjątki unchecked
dziedziczą po klasie RuntimeException
lub Error
i nie jest wymagają obsługi lub deklaracji w kodzie. Jednakże, choć nie jest to wymagane, dobrą praktyką jest obsługiwanie wyjątków unchecked, jeśli istnieje prawdopodobieństwo ich wystąpienia. Ponadto, ważne jest unikanie sytuacji, które mogą spowodować wystąpienie takiego wyjątku poprzez stosowanie odpowiednich zabezpieczeń i sprawdzanie warunków w kodzie.
int[] array = {1, 2, 3}; try { int value = array[4]; // spowoduje ArrayIndexOutOfBoundsException } catch (ArrayIndexOutOfBoundsException e) { // obsługa wyjątku ArrayIndexOutOfBoundsException }
⬅️ Przykłady
NullPointerException
:
Występuje podczas próby użycia odwołania do obiektu, który nie istnieje (null)
ArrayIndexOutOfBoundsException
:
Ten wyjątek pojawia się podczas próby dostępu do elementu tablicy poza jej zakresem
ClassCastException
:
Występuje podczas rzutowania obiektu na niekompatybilny typ.
NumberFormatException
:
Ten wyjątek występuje, gdy próba parsowania łańcucha znaków na liczbę jest niemożliwa z powodu nieprawidłowego formatu
ArithmeticException
:
Występuje, gdy pojawi się błąd arytmetyczny, np. dzielenie przez zero
IllegalArgumentException
:
Ten wyjątek jest rzucany, gdy przekazane do metody argumenty są niepoprawne
StackOverflowError
:
Jest zgłaszany, gdy stos wywołań przekracza dostępny limit
Śledź moją aktywność na Linkedin
Zapisz się na mój newsletter:
Popełnianie błędów jest rzeczą naturalną zanim perfekcyjnie opanujemy nowy materiał. Jeśli wyłapałeś jakieś nieprawidłowości w moim tekście, proszę daj mi znać mailowo. Jeśli masz jakieś sugestie lub pytania, proszę napisz do mnie wiadomość: kuba@javampokaze.pl