CodeGym /Kurslar /JAVA 25 SELF /finally və throw: tamamlanma və istisna atılması

finally və throw: tamamlanma və istisna atılması

JAVA 25 SELF
Səviyyə , Dərs
Mövcuddur

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?

  1. try daxilində iki ədədi bölməyə cəhd edirik və xəta alırıq.
  2. Bölmə zamanı xəta baş verərsə — catch onu emal edəcək.
  3. 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:

  1. Proqram məcburi şəkildə bu əmrlə dayandırılıb: System.exit(0).
  2. finally icra olunan axın məcburi olaraq “öldürülüb”.
  3. 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ı");

ExceptionTypeThrowable-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);
}
Şərhlər
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION