Wyjątki lub sytuacje wyjątkowe (stany) to błędy, które pojawiają się w programie podczas jego działania. Wszystkie wyjątki w Javie są obiektami. Mogą być zatem generowane nie tylko automatycznie w przypadku wystąpienia wyjątkowej sytuacji, ale także tworzone przez samego dewelopera. Hierarchia klas wyjątków: Wyjątki są podzielone na kilka klas, ale wszystkie mają wspólnego przodka – klasę
Throwable
. Jego potomkami są podklasy Exception
i Error
. Wyjątki ( Exceptions
) są wynikiem problemów w programie, które w zasadzie można rozwiązać i przewidzieć. Na przykład dzielenie przez zero wystąpiło w liczbach całkowitych. Błędy ( Errors
) to poważniejsze problemy, które według specyfikacji Java nie powinny być naprawiane we własnym programie, ponieważ są to problemy na poziomie maszyny JVM. Na przykład wyjątki tego rodzaju występują w przypadku wyczerpania się pamięci dostępnej dla maszyny wirtualnej. Program w dalszym ciągu nie będzie w stanie zapewnić dodatkowej pamięci dla maszyny JVM. W Javie wszystkie wyjątki są podzielone na trzy typy: wyjątki sprawdzone ( checked
) i wyjątki niesprawdzone ( unchecked
), które obejmują błędy ( Errors
) i wyjątki czasu wykonywania ( RuntimeExceptions
potomek klasy Exception
). Kontrolowane wyjątki to błędy, które mogą i powinny być obsługiwane w programie; wszyscy potomkowie klasy Exception
(ale nie RuntimeException
) należą do tego typu. Obsługa wyjątków może odbywać się za pomocą operatorów try…catch
lub przenieść do zewnętrznej części programu. Na przykład metoda może przekazywać wyjątki, które występują w niej wyżej w hierarchii wywołań, bez samodzielnej obsługi. Niesprawdzone wyjątki nie wymagają obsługi, ale jeśli chcesz, możesz obsłużyć wyjątki klasowe RuntimeException
. Skompilujmy i uruchommy następujący program:
class Main {
public static void main(String[] args) {
int a = 4;
System.out.println(a/0);
}
}
Po uruchomieniu na konsoli wyświetli się następujący komunikat:
Exception in thread "main" java.lang.ArithmeticException: / by zero
at Main.main(Main.java:4)
Komunikat pokazuje klasę wyjątku, który wystąpił - ArithmeticException
. Ten wyjątek można obsłużyć:
class Main {
public static void main(String[] args) {
int a = 4;
try {
System.out.println(a/0);
} catch (ArithmeticException e) {
System.out.println("Произошла недопустимая арифметическая операция");
}
}
}
Teraz zamiast standardowego komunikatu o błędzie zostanie wykonany blok catch
, którego parametrem jest obiekt e klasy odpowiadający wyjątkowi (samemu obiektowi można nadać dowolną nazwę, będzie ona potrzebna jeśli będziemy chcieli na siłę rzucić na przykład ponownie ten wyjątek, aby został sprawdzony przez inną procedurę obsługi). W tym przypadku blok try
zawiera fragment programu, w którym potencjalnie mógłby wystąpić wyjątek. Można try
odpowiadać kilku blokom catch z różnymi klasami wyjątków.
import java.util.Scanner;
class Main {
public static void main(String[] args) {
int[] m = {-1,0,1};
Scanner sc = new Scanner(System.in);
try {
int a = sc.nextInt();
m[a] = 4/a;
System.out.println(m[a]);
} catch (ArithmeticException e) {
System.out.println("Произошла недопустимая арифметическая операция");
} catch (ArrayIndexOutOfBoundsException e) {
System.out.println("Обращение по недопустимому индексу массива");
}
}
}
Jeżeli po uruchomieniu prezentowanego programu użytkownik wejdzie z klawiatury 1 lub 2, program uruchomi się bez tworzenia wyjątków. Jeśli użytkownik wprowadzi 0, nastąpi wyjątek klasy ArithmeticException
, który zostanie obsłużony przez pierwszy blok catch
. Jeśli użytkownik wprowadzi 3, nastąpi wyjątek klasy ArrayIndexOutOfBoundsException
(tablica poza zakresem) i zostanie on przetworzony przez drugi blok catch
. Jeśli użytkownik wprowadzi liczbę niecałkowitą, na przykład 3,14, wystąpi wyjątek klasy InputMismatchException
(niezgodność typu danych wejściowych) i zostanie on wyrzucony w standardowym formacie błędu, ponieważ w żaden sposób sobie z tym nie poradziliśmy. Możesz jednak dodać procedurę obsługi dla klasy Exception
, ponieważ ta klasa jest klasą nadrzędną dla wszystkich innych sprawdzanych wyjątków, przechwyci każdy z nich (w tym InputMismatchException
).
import java.util.Scanner;
class Main {
public static void main(String[] args) {
int[] m = {-1,0,1};
int a = 1;
Scanner sc = new Scanner(System.in);
try {
a = sc.nextInt();
m[a-1] = 4/a;
System.out.println(m[a]);
} catch (ArithmeticException e) {
System.out.println("Произошла недопустимая арифметическая операция");
} catch (ArrayIndexOutOfBoundsException e) {
System.out.println("Обращение по недопустимому индексу массива");
} catch (Exception e) {
System.out.println("Произошло ещё Jakое-то исключение");
}
}
}
Ponieważ wyjątki są zbudowane na podstawie hierarchii klas i podklas, powinieneś najpierw spróbować obsłużyć bardziej szczegółowe wyjątki, a dopiero potem bardziej ogólne. Oznacza to, że jeśli umieścimy pierwszy (a nie trzeci) blok z obsługą wyjątków klas Exception
, nigdy nie zobaczymy żadnych komunikatów o błędach innych niż „Wystąpił jakiś inny wyjątek” (wszystkie wyjątki zostaną natychmiast przechwycone przez ten blok i nie dotrą do reszta). Opcjonalnym dodatkiem do bloków try…catch
może być klocek finally
. Umieszczone w nim polecenia zostaną wykonane w każdym przypadku, niezależnie od tego, czy wystąpi wyjątek, czy nie. Pomimo tego, że w przypadku wystąpienia nieobsłużonego wyjątku, część programu pozostała po wygenerowaniu tego wyjątku nie jest wykonywana. Na przykład, jeśli podczas niektórych długotrwałych obliczeń wystąpił wyjątek, finally
możesz wyświetlić lub zapisać wyniki pośrednie w bloku. Link do źródła: Wyjątki i ich obsługa
GO TO FULL VERSION