Məqalələr

Java sertifikat imtahanına hazırlaşmağın faydalarından biri

advantage-of-java-certification
Written by Mushfiq Mammadov

Bu məqalədə sertifikat imtahanına hazırlaşmağın sizə verəcəyi bir faydaya toxunacam. Dünən maraqlı bir problemlə rastlaşdım və başa düşdüm ki, sertifikat imtahanına hazırlaşmasaydım problemin həll yolunu axtarmaq bir yana qalsın, heç problemin səbəbini başa düşməyəcəkdim. Çünki fundamental java kitabları oxuyarkən çox xırda detallara elə də diqqət yetirmirik, amma sertifikat imtahanı suallarında həmin mövzularla o qədər rastlaşırıq ki, artıq beynimizin bir küncündə özünə yer edir.

Anlaşıqlı olsun deyə sadə bir kod nümunəsi yazacam və problemin nə olduğunu həmin kod üzərindən qeyd edəcəm:

package az.mm.runnable;

import java.io.IOException;

public class Controller {

    public static void main(String[] args) {
        Service service = new Service();
        service.sendMessage();
    }
}

class Service {

    void sendMessage() {
        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                try {
                    // do something
                    throw new IOException();
                } catch (IOException ex) {
                }
            }
        };

        Thread thread = new Thread(runnable);
        thread.start();
    }
}

Tutaq ki, bir Controller classı var, web servisə gələn sorğuları qəbul edir və Service classındakı sendMessage() metodunu işlədir. Çox detallara getməyəcəm, koddan hər şey aydın görünəcək. Deməli burada çatışmazlıq nədir: əgər run() metodunda xəta baş versə, catch blokunda xəta yaxalanacaq və Controller classının bundan xəbəri olmayacaq. Əslində bizə lazımdır ki, run() metodunda xəta baş verərsə, bu xətanı Controller classına ötürək və Controller classı da öz növbəsində bu xətanı sorğunu göndərən clint`ə bildirsin. Client də mesajının göndərilmədiyi barədə məlumatlı olsun. Bunun üçün biz catch blokunda xətanı qeydə alıb logladıqdan sonra yenidən onu Controller classına throw edə bilərik, yəni bu formada:

    try {
        // do something
        throw new IOException();
    } catch (IOException ex) {
        System.out.println(ex);
        throw ex; // line a
    }

Amma “line a” sətri compile xətası verir. Bax işin bütün məğzi bu xətanın səbəbini tapmaqdır və bu mövzuda toxunmaq istədiyim əsas məsələ də elə budur. Artıq burada sertifikat imtahanına hazırlaşarkən öyrəndiklərimiz köməyimizə çatır 🙂

Əvvəlcə sadə yanaşma ilə fikirləşə bilərik ki, əgər  catch blokunda yenidən “checked exception” fırladılarsa, o yenidən ya “handle” edilməlidir, ya da “declare”. Amma bizə “declare” olunması lazımdır, bunun üçün public void run() throws IOException yazmalıyıq. Amma bu da bizə kömək etmir, yenə compile xətası alırıq, bir az daha dərinə enməliyik.

run() metodu Runnable interfeysinə aid olan abstract metoddur və biz onu override edirik. Compile xətasının səbəbi də metodlar üçün override olunma qaydalarının pozulması ilə əlaqədardır. Əvvəlcə baxaq ki, düzgün override olunmuş metod hansı qaydalara riayət etməlidir:

  1. Child classdakı metod parent classdakı metod ilə eyni quruluşa (the same signature) malik olmalıdır. Yəni, metod adları və parametr siyahısı mütləq eyni olmalıdır.
  2. Child classdakı metodun access modifier`i parent classdakı metodla ən azı eyni olmalıdır, ya da ki, daha yüksək.
  3. Parent classdakı metodun fırlatdığı (throws) checked exceptionun tipi həmişə child classdakı metoddan daha geniş olmalıdır. Child classdakı metod maksimum halda eyni exception tipini fırlada, yaxud da kiçik tip, və yaxud da heç exception fırlatmaya da bilər.
  4. Hər iki metodun geriyə döndürdüyü dəyər eyni tipdə olmalıdır və ya override edilən/parent classdakı metodun subclassı (covariant return types).
  5. *private metodlar override oluna bilməz.

Deməli, bizdə 3-cü qaydanın tələbləri pozulub, çünki Runnable interfeysindəki run() metodunun strukturu belədir:

  •     public abstract void run();

Göründüyü kimi bu metod heç bir Exception fırlatmır, ona görə də biz IOException`u throws edə bilmərik, başqa həll variantları fikirləşməliyik.

İnternetdə baxdım fərqli həllər təklif edilmişdi, amma özümün ağlına maraqlı bir həll variantı gəldi, onun üzərində dayandım, fikirləşirəm ki, işimə yarıya bilər. Deməli, metod override qaydaları ilə bağlı 3-cü şərtə diqqətlə baxsaq görərik ki, söhbət ancaq “checked” exceptionlardan gedir, bu məhdudiyyət “unchecked” exceptionlara tətbiq edilmir. Aha deməli mənə xətanın baş verib verməməsini bilmək lazımdır və əgər baş veribsə, onu mətnini client`ə göstərməliyəm. Ona görə də mən catch blokunda “unchecked exception” fırlada və həmin exceptionun konstruktoru vasitəsilə original exceptionun mətnini göndərə bilərəm:

package az.mm.runnable;

import java.io.IOException;

public class Controller {

    public static void main(String[] args) {     
        Service service = new Service();
        service.sendMessage();   
    }
}

class Service {  

    void sendMessage() {
        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                try {
                    throw new IOException();
                } catch (IOException ex) {
                    throw new RuntimeException(ex);
                }
            }
        };

        Thread thread = new Thread(runnable);
        thread.start();
    }
}

Əgər thread`lərin işləmə məntiqi ilə bir uyğunsuzluq yaranmasa, ümid edirəm bu həll variantı işimə yarıyacaq. Əgər həll variantında əksikliklər olarsa və dəyişməli olsam, məqaləni yeniləyib burada qeyd edəcəm İnşallah.

About the author

Mushfiq Mammadov

Leave a Comment


The reCAPTCHA verification period has expired. Please reload the page.

 

This site uses Akismet to reduce spam. Learn how your comment data is processed.