1. finally bloku ilə tanışlıq
Resurslarla — fayllar, şəbəkə bağlantıları, verilənlər bazaları — işləyərkən onların bağlanacağı və ya həmişə azad ediləcəyi barədə əmin olmaq vacibdir, hətta icra zamanı xəta baş versə belə. Java-da bunun üçün xüsusi bir blok var — finally.
finally necə işləyir?
finally bloku try-catch-finally konstruksiyasının bir hissəsidir. finally daxilindəki kod həmişə icra olunur (əgər yazılıbsa) — istisnanın olub-olmamasından asılı olmayaraq. Hətta try daxilində return olsa və ya istisna atılsa belə — finally yenə də icra olunacaq (yalnız kompüteri söndürməsəniz və ya proqramı System.exit(0) vasitəsilə məcburi dayandırmasanız).
Sintaksis:
try {
// İstisna yarana biləcək kod
} catch (ExceptionType e) {
// Xəta emalı
} finally {
// Bu kod həmişə icra olunacaq!
}
Nümunə
try {
System.out.println("İcra başlanır");
int result = 10 / 0; // burada xəta baş verəcək
System.out.println("Nəticə: " + result);
} catch (ArithmeticException e) {
System.out.println("Xəta: sıfıra bölmə");
} finally {
System.out.println("Bu kod istənilən halda icra olunacaq");
}
Nəticənin icrası:
İcra başlanır
Xəta: sıfıra bölmə
Bu kod istənilən halda icra olunacaq
Nə baş verir?
- try daxilində iki ədədi bölməyə cəhd edirik və xəta alırıq.
- Bölmə zamanı xəta baş verərsə — catch onu emal edəcək.
- Amma! Hər halda finally icra olunur və konsola mesaj yazır.
2. catch olmadan finally
Konstruksiyanın 3 variantı ola bilər:
- Tam: try-catch-finally
- finally olmadan: try-catch
- catch olmadan: try-finally
Üçüncü variant ondan istifadə olunur ki, xətanı tutmaq və emal etmək yuxarı səviyyədəki metod tərəfindən yerinə yetirilsin. Amma finally bloku müəyyən kodun mütləq icrasını təmin etmək üçün lazımdır:
- Faylların, şəbəkə bağlantılarının, verilənlər bazalarının bağlanması.
- İstənilən resursların azad edilməsi (məsələn, kilidlərin açılması).
- Loqlaşdırma: əməliyyatın tamamlanması barədə məlumatın yazılması.
Nümunə:
try {
System.out.println("Ədədləri bölürük");
int result = 10 / 0; // xəta!
System.out.println("Nəticə: " + result);
} finally {
System.out.println("finally bloku icra olundu");
}
Nəticə:
Ədədləri bölürük
finally bloku icra olundu
Exception in thread "main" java.lang.ArithmeticException: / by zero
finally nə zaman icra olunmur?
Demək olar ki, həmişə icra olunur. İstisnalar — aşağıdakılardır:
- Proqram məcburi şəkildə bu əmrlə dayandırılıb: System.exit(0).
- finally icra olunan axın məcburi olaraq “öldürülüb”.
- Kompüter söndürülüb.
3. throw operatoru: istisnanı özünüz necə ata bilərsiniz
Bəzən Java özü istisna “atar” (məsələn, sıfıra bölmə, massiv sərhədlərindən kənara çıxma). Amma elə hallar olur ki, siz açıq şəkildə bildirmək istəyirsiniz: “Bu, xətadır! İcraya davam edə bilmirəm!”. Bunun üçün Java-da throw operatoru var.
Analoji: Mağazada vaxtı keçmiş məhsul görürsünüzsə — “şikayət” edirsiniz. Kodda da belədir: nəsə qaydasında deyilsə — istisna atırsınız.
throw sintaksisi
throw new ExceptionType("Xəta mesajı");
ExceptionType — Throwable-dan miras alan istənilən sinifdir (adətən Exception və ya RuntimeException). Mötərizədə — nəyi səhv getdiyini anlamağa kömək edən mesajdır.
Nümunə: metod arqumentlərinin yoxlanması
public static int safeDivide(int a, int b) {
if (b == 0) {
throw new IllegalArgumentException("Bölən sıfıra bərabər ola bilməz");
}
return a / b;
}
İstifadə:
public static void main(String[] args) {
try {
int result = safeDivide(10, 0);
System.out.println("Nəticə: " + result);
} catch (IllegalArgumentException e) {
System.out.println("Xəta: " + e.getMessage());
}
}
Nəticə:
Xəta: Bölən sıfıra bərabər ola bilməz
throw nə vaxt istifadə olunur?
- Metod arqumentlərinin yoxlanması (məsələn, null gəlibsə və ya qeyri-düzgün məlumatdırsa).
- Obyektin vəziyyətinin yoxlanması (məsələn, balansında 0 avro olan hesabdan pul çıxarmağa cəhd).
- catch daxilində — istisnanı daha yuxarı səviyyəyə “yenidən atmaq” istəsəniz (məsələn, əlavə məlumat qoşmaq üçün).
4. try-catch-finally və throw birlikdə
Bəzən bu konstruksiyalar birlikdə işləyir. Məsələn, bir xətanı tutursunuz, sonra isə daha informativ olan öz istisnanızı atmağa qərar verirsiniz.
public static int parseAndDivide(String text, int divisor) {
try {
int number = Integer.parseInt(text);
if (divisor == 0) {
throw new IllegalArgumentException("Bölən sıfıra bərabər ola bilməz");
}
return number / divisor;
} catch (NumberFormatException e) {
throw new IllegalArgumentException("Sətir '" + text + "' rəqəm deyil");
} finally {
System.out.println("Sətiri emal etməyə cəhd: " + text);
}
}
İstifadə:
try {
int result = parseAndDivide("42a", 2);
System.out.println("Nəticə: " + result);
} catch (IllegalArgumentException e) {
System.out.println("Xəta: " + e.getMessage());
}
Nəticə:
Sətiri emal etməyə cəhd: 42a
Xəta: Sətir '42a' rəqəm deyil
Vacib nüans: return və finally
Hətta try blokunda return olsa da, finally yenə də icra olunacaq!
public static int getValue() {
try {
return 10;
} finally {
System.out.println("finally yenə də işləyəcək!");
}
}
getValue() çağırışı belə çıxış verəcək:
finally yenə də işləyəcək!
5. finally və throw istifadə edərkən tipik səhvlər
Səhv №1: finally olmadan resursu bağlamağı unutmaq.
Çox rast gəlinən problem: faylı açmısınız, bağlamamısınız — resurs sızması alırsınız. Həmişə finally-dən (və ya sonradan danışacağımız try-with-resources-dən) istifadə edin.
Səhv №2: istisna atıldı, amma emal olunmadı.
Əgər throw ilə istisna atırsınızsa, amma heç yerdə onu tutmursunuzsa (try-catch yoxdur), proqram qəza ilə dayanacaq. Həmişə düşünün: sizin istisnanızı kim tutacaq.
Səhv №3: finally daxilində return.
Səhvən return ifadəsini finally içində yazsanız, o, əvvəlki bütün return və ya throw-ları “üstələyəcək”. Bu, çox çətin aşkarlanan xətalara gətirib çıxara bilər. Belə etmək qətiyyən tövsiyə olunmur!
public int tricky() {
try {
return 1;
} finally {
return 2; // TƏHLÜKƏLİ: 1 deyil, 2 qaytarılacaq!
}
}
Nəticə: 2 qaytarılacaq, baxmayaraq ki, try içində 1 idi.
Səhv №4: istisna haqqında məlumatın itirilməsi.
Bir istisnanı tutub sonra yenisini atırsınızsa və köhnə haqda məlumatı (e) saxlamırsınızsa, çağırış stekini itirirsiniz ki, bu da sazlanmanı çətinləşdirir. Daha yaxşısı belə yazmaqdır:
catch (NumberFormatException e) {
throw new IllegalArgumentException("Çevrilmə xətası", e);
}
GO TO FULL VERSION