1. Bir neçə catch: müxtəlif istisnaların işlənməsi
Real proqramlarda eyni kod bloku müxtəlif tip istisnalar ata bilər. Məsələn, fayl oxunarkən həm FileNotFoundException, həm də IOException yarana bilər, verilənlərin parsinqi zamanı isə əlavə olaraq NumberFormatException baş verə bilər. Hər vəziyyəti düzgün emal etmək üçün Java-da ard-arda bir neçə catch bloku istifadə etmək olar.
Sintaksis
try {
// təhlükəli əməliyyatlar
} catch (FileNotFoundException e) {
System.out.println("Fayl tapılmadı: " + e.getMessage());
} catch (IOException e) {
System.out.println("Giriş-çıxış xətası: " + e.getMessage());
} catch (NumberFormatException e) {
System.out.println("Yanlış rəqəm formatı: " + e.getMessage());
}
Vacib məqam:
catch blokları daha spesifikdən daha ümumi olana doğru düzülməlidir! Əgər əvvəlcə catch (Exception e) yazsanız, qalan bloklar əlçatmaz olacaq və kompilyator xəta verəcək.
Bu niyə vacibdir?
- Spesifik emal: Fərqli xətalara fərqli reaksiya vermək olar (məsələn, başqa fayl seçməyi təklif etmək və ya girişi təkrarlamaq).
- Oxunaqlılıq: Kod daha anlaşılan olur — hansı xətaların gözlənildiyi və necə emal edildiyi görünür.
2. Bir neçə tiplə catch (multi-catch)
Bəzən müxtəlif istisnalar üçün eyni emal tələb olunur. Məsələn, oxu xətası və ya rəqəmin çevrilməsi xətası olmasından asılı olmayaraq, sadəcə xəta mesajını çıxarmaq və ya onu loqa yazmaq istəyirsiniz.
Java 7-dən etibarən bir blokda bir neçə istisna tipini birləşdirməyə imkan verən multi-catch sintaksisi mövcuddur:
try {
// təhlükəli əməliyyat
} catch (IOException | NumberFormatException e) {
System.out.println("Faylın və ya rəqəmin emalı zamanı xəta: " + e.getMessage());
}
Bu necə işləyir:
- Şaquli xətt (|) vasitəsilə istisna tipləri göstərilir.
- e dəyişəni ən ümumi baza sinfinin tipinə (adətən Exception) sahib olacaq.
- Blok daxilində e dəyişəninə yeni dəyər mənimsətmək olmaz — o, avtomatik olaraq final sayılır.
Nümunə:
try {
BufferedReader reader = new BufferedReader(new FileReader("numbers.txt"));
String line = reader.readLine();
int number = Integer.parseInt(line);
System.out.println("Rəqəm: " + number);
reader.close();
} catch (IOException | NumberFormatException e) {
System.out.println("Xəta: " + e.getMessage());
}
3. İstisnaların işlənməsi üzrə ən yaxşı təcrübələr
İstisnaları gizlətməyin
Pisdir:
try {
// nəsə təhlükəli
} catch (Exception e) {
// heç nə etmirik!
}
Niyə pisdir?
Boş catch bloku xətanı “gizlədir” — nasazlığın səbəbi barədə məlumatı itirirsiniz və proqramın sazlanması mümkünsüzləşir.
Daha yaxşı: heç olmasa mesaj çıxarın və ya xətanı loqlayın.
catch (Exception e) {
e.printStackTrace();
}
İstisnanı emal edə bilmirsinizsə — onu yuxarıya ötürün:
catch (IOException e) {
throw e; // yaxud new RuntimeException(e) atın
}
Ən spesifik istisnaları atın
Öz metodlarınızı və ya API yazırsınızsa, Exception və ya RuntimeException yerinə həmişə mümkün qədər konkret istisnalar atın. Bu, sizin kodunuzu və interfeysi digər tərtibatçılar üçün daha anlaşılan edir.
Nümunə:
public void withdraw(double amount) throws InsufficientFundsException {
if (amount > balance) {
throw new InsufficientFundsException("Hesabda kifayət qədər vəsait yoxdur");
}
// ...
}
Proqramın idarəetmə axını üçün istisnalardan istifadə etməyin
İstisnalar istisnai vəziyyətlərin — yəni proqramın normal işləməsi zamanı baş verməməli olan xətaların — emalı üçün nəzərdə tutulub. Onlardan adi məntiq üçün (məsələn, dövrdən çıxış və ya şərtlərin yoxlanması) istifadə etməyin.
Pisdir:
try {
while (true) {
String line = reader.readLine();
if (line == null) break;
// sətirin emalı
}
} catch (Exception e) {
// dövrdən çıxmaq üçün istisnadan istifadə edirik — pisdir!
}
Yaxşıdır:
String line;
while ((line = reader.readLine()) != null) {
// sətirin emalı
}
4. Praktiki nümunələr
Nümunə: müxtəlif xətaların fərqli emalı
try {
BufferedReader reader = new BufferedReader(new FileReader("data.txt"));
String line = reader.readLine();
int number = Integer.parseInt(line);
System.out.println("Rəqəm: " + number);
reader.close();
} catch (FileNotFoundException e) {
System.out.println("Fayl tapılmadı!");
} catch (IOException e) {
System.out.println("Faylın oxunmasında xəta!");
} catch (NumberFormatException e) {
System.out.println("Faylda rəqəm deyil!");
}
Nümunə: eyni emal üçün multi-catch
try {
// nəsə təhlükəli
} catch (IOException | NumberFormatException e) {
System.out.println("Xəta: " + e.getMessage());
}
5. Vacib nüanslar və tipik səhvlər
Xəta № 1: catch bloklarının yanlış sırası. Əvvəlcə daha spesifik istisnalar, sonra — ümumi olanlar gəlməlidir. Əks halda geniş bloka heç vaxt çatılmayacaq.
Xəta № 2: multi-catch-də miras əlaqəsi olan tiplərin istifadəsi. Məsələn, catch (IOException | Exception e) kompilyasiya olunmayacaq, çünki IOException Exception-dan miras alır.
Xəta № 3: multi-catch-də e dəyişənini dəyişməyə cəhd. Bu halda e final sayılır — ona yeni dəyər mənimsətmək olmaz.
Xəta № 4: boş catch blokları. Xətaların nəzərə alınmaması “səssiz” bağlara gətirib çıxarır. Minimum — mesaj çıxarın və ya istisnanı loqlayın.
Xəta № 5: bütün Exception-u tutmaq. catch (Exception e) istifadə etmək real problemləri gizlədir və sazlamanı çətinləşdirir. Yaxşısı yalnız gözlənilən istisnaları tutmaqdır.
GO TO FULL VERSION