- İstisnanın nə olduğunu izah etmək və stek izini oxumaq
try,catchvəfinallybloklarından istifadə etmək- Yoxlanılan və yoxlanılmayan istisnaları fərqləndirmək və öz istisna sinfini yazmaq
İstifadəçi yaş yerinə «abc» yazdı, fayl silinib, internet kəsildi — real proqramlarda hər şey plan üzrə getmir. Yaxşı proqram belə hallarda «çökmür», problemi nəzakətlə bildirir və işini davam etdirir. Java-da gözlənilməz vəziyyətləri istisnalar (exceptions) vasitəsilə idarə edirlər.
İstisna nədir?
İstisna proqramın normal axınını pozan hadisəni təsvir edən obyektdir. İstisna baş verəndə Java onu «atır» (throw): cari metod dərhal dayanır və istisna onu tutacaq kod tapılana qədər çağırışlar zənciri ilə yuxarı qalxır. Heç kim tutmasa, proqram dayanır və konsola stek izi (stack trace) çıxır.
public class Main {
public static void main(String[] args) {
int[] marks = {5, 4, 3};
System.out.println("Start");
System.out.println(marks[5]);
System.out.println("End");
}
}Start Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: Index 5 out of bounds for length 3 at Main.main(Main.java:5)
Stek izini aşağıdan yuxarı deyil, yuxarıdan aşağı oxu: əvvəlcə istisnanın tipi (ArrayIndexOutOfBoundsException), sonra mesajı (5-ci indeks 3 uzunluqlu massivdən kənardadır), sonra isə harada baş verdiyi — Main.java faylının 5-ci sətri. «End» çap olunmadı: istisnadan sonra metodun qalan hissəsi icra olunmur.
try, catch və finally
Təhlükəli kodu try blokuna yerləşdiririk. İstisna baş verərsə, idarəetmə uyğun tipli catch blokuna keçir. finally bloku isə hər halda — istisna olsa da, olmasa da — icra olunur; orada adətən faylı və ya bağlantını bağlamaq kimi «yığışdırma» işləri görülür.
public class Main {
public static void main(String[] args) {
String[] inputs = {"42", "abc", "0"};
for (String input : inputs) {
try {
int n = Integer.parseInt(input);
System.out.println("100 / " + n + " = " + (100 / n));
} catch (NumberFormatException e) {
System.out.println("Not a number: " + e.getMessage());
} catch (ArithmeticException e) {
System.out.println("Math error: " + e.getMessage());
} finally {
System.out.println("-- checked \"" + input + "\"");
}
}
}
}100 / 42 = 2 -- checked "42" Not a number: For input string: "abc" -- checked "abc" Math error: / by zero -- checked "0"
Integer.parseInt("abc")mətni ədədə çevirə bilmir vəNumberFormatExceptionatır.- Tam ədədin sıfıra bölünməsi
ArithmeticExceptionyaradır. (Maraqlıdır ki,100.0 / 0istisna atmır vəInfinityverir.) e.getMessage()istisnanın mesajını qaytarır. Proqram istisnadan sonra dayanmadı — dövr növbəti qiymətlə davam etdi.finallyhər üç halda işlədi.
Yoxlanılan və yoxlanılmayan istisnalar
Bütün istisnaların ümumi valideyni Throwable-dır. Ondan Error (JVM-in ciddi problemləri, məsələn, yaddaşın bitməsi — onları adətən tutmurlar) və Exception törəyir. Exception-ın isə xüsusi bir qolu var — RuntimeException. Bu bölgü Java-nın unikal qaydasını müəyyən edir:
| Xüsusiyyət | Yoxlanılan (checked) | Yoxlanılmayan (unchecked) |
|---|---|---|
| Kimdən törəyir | Exception (amma RuntimeException yox) | RuntimeException |
| Kompilyator tələb edir? | bəli: tut və ya throws ilə elan et | xeyr |
| Adətən nə deməkdir | proqramdan asılı olmayan problem | proqramçının səhvi |
| Nümunələr | IOException, FileNotFoundException | NullPointerException, ArithmeticException, IllegalArgumentException |
Məsələn, new FileReader("data.txt") yazıb onu try içinə almasan, kod kompilyasiya olunmayacaq: unreported exception FileNotFoundException; must be caught or declared to be thrown. Kompilyator sanki deyir: «Fayl olmaya bilər — bu halda nə edəcəyini qabaqcadan düşün».
throw, throws və öz istisnaların
İstisnanı özün də ata bilərsən: throw new IllegalArgumentException("..."). Bu, metodun yanlış məlumat qəbul etməsinin qarşısını almağın ən yaxşı yoludur. Öz istisna sinfini yaratmaq üçün Exception (yoxlanılan) və ya RuntimeException (yoxlanılmayan) sinfindən törəmə sinif yaz. Yoxlanılan istisna atan metod bunu başlığında throws ilə elan etməlidir.
public class Main {
static void setAge(int age) {
if (age < 0 || age > 150) {
throw new IllegalArgumentException("Invalid age: " + age);
}
System.out.println("Age set to " + age);
}
public static void main(String[] args) {
try {
setAge(25);
setAge(-3);
setAge(40);
} catch (IllegalArgumentException e) {
System.out.println("Error: " + e.getMessage());
}
System.out.println("Program continues");
}
}Age set to 25 Error: Invalid age: -3 Program continues
setAge(40) heç vaxt çağırılmadı: setAge(-3) istisna atan kimi try bloku dayandı və idarəetmə catch-ə keçdi. İndi isə öz yoxlanılan istisnamızı yaradaq — pul kisəsində pul çatmayanda:
public class Main {
public static void main(String[] args) {
Wallet wallet = new Wallet(30);
try {
wallet.pay(12);
wallet.pay(25);
} catch (InsufficientFundsException e) {
System.out.println(e.getMessage());
System.out.println("Missing: " + e.getMissing() + " AZN");
}
}
}
class InsufficientFundsException extends Exception {
private final double missing;
InsufficientFundsException(double missing) {
super("Not enough money in the wallet");
this.missing = missing;
}
double getMissing() { return missing; }
}
class Wallet {
private double balance;
Wallet(double balance) { this.balance = balance; }
void pay(double amount) throws InsufficientFundsException {
if (amount > balance) {
throw new InsufficientFundsException(amount - balance);
}
balance -= amount;
System.out.println("Paid " + amount + ", left " + balance);
}
}Paid 12.0, left 18.0 Not enough money in the wallet Missing: 7.0 AZN
Əsas fikirlər
- İstisna normal axını pozan hadisədir; tutulmazsa, proqram dayanır və stek izi çap olunur.
trytəhlükəli kodu,catchmüəyyən tipli istisnanı tutur,finallyisə hər zaman icra olunur.- Yoxlanılan istisnaları (
IOException) tutmaq və yathrowsilə elan etmək məcburidir;RuntimeExceptiontörəmələri isə yoxlanılmır. throw new ...istisnanı atır; öz istisnan üçünExceptionvə yaRuntimeException-dan törəyən sinif yaz.- Boş
catchbloku yazma — xəta haqqında məlumat itir.
Özünü yoxla
10 sual. Hər düzgün cavab XP qazandırır.
finally bloku nə vaxt icra olunur?