CodeGym /Kurslar /JAVA 25 SELF /Standart kitabxanadakı interfeyslər: Comparable, Serializ...

Standart kitabxanadakı interfeyslər: Comparable, Serializable və s.

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

1. Interfeys Comparable<T>

Heç vaxt rəqəmlər və ya sətirlər siyahısını sıralamısınız? Əlbəttə, bəli! İndi isə təsəvvür edin ki, sizin öz obyektlərinizin siyahısı var — məsələn, tələbələr, mallar və ya pişiklər. Java onların hansı qaydada sıralanacağını necə başa düşəcək? Məhz bunun üçün Comparable<T> interfeysi lazımdır.

Bu interfeys obyektlərin “təbii sıralamasını” müəyyən edir — yəni həmin məlumat növü üçün məntiqli olan qaydanı. Məsələn, rəqəmlər üçün — artan, sətirlər üçün — əlifba üzrə, tələbələr üçün — soyad və ya yaşa görə (sizin seçiminiz).

Comparable necə qurulub

Interfeys çox sadədir: onda cəmi bir metod var:

public interface Comparable<T> {
    int compareTo(T o);
}

compareTo metodu aşağıdakıları qaytarmalıdır:

  • mövcud obyekt digərindən “kiçikdirsə”, mənfi ədəd;
  • 0 — “bərabərdirsə”;
  • müsbət ədəd — “böyükdürsə”.

Nümunə: tələbələri yaşa görə sıralayırıq

Gəlin, Student sinfini əlavə edib onun üçün Comparable<Student> interfeysini reallaşdıraq:

public class Student implements Comparable<Student> {
    private String name;
    private int age;

    public Student(String name, int age) {
        this.name = name;
        this.age = age;
    }

    // Nümunə üçün getter-lər
    public String getName() { return name; }
    public int getAge() { return age; }

    @Override
    public int compareTo(Student other) {
        // Yaşa görə sıralayırıq (artan)
        return Integer.compare(this.age, other.age);
    }

    @Override
    public String toString() {
        return name + " (" + age + ")";
    }
}

İndi tələbələrin massivini və ya siyahısını asanlıqla sıralaya bilərik:

import java.util.*;

public class Main {
    public static void main(String[] args) {
        List<Student> students = new ArrayList<>();
        students.add(new Student("Vasya", 20));
        students.add(new Student("Petya", 18));
        students.add(new Student("Masha", 22));

        Collections.sort(students); // Comparable sayəsində işləyir!

        System.out.println("Sıralanmış tələbələr:");
        for (Student s : students) {
            System.out.println(s);
        }
    }
}

Nəticə:

Petya (18)
Vasya (20)
Masha (22)

Vacib məqam

Əgər Comparable reallaşdırırsınızsa, çalışın ki, compareTo metodu equals ilə uyğun işləsin. Yəni əgər a.compareTo(b) == 0 isə, a.equals(b)true olmalıdır. Əks halda sıralama və kolleksiyalar gözlənilməz davrana bilər və proqramçının həyatının mənası barədə əlavə fəlsəfi düşüncələriniz yarana bilər.

2. Interfeys Serializable

Seriyalaşdırma — obyektin bayt ardıcıllığına çevrilməsi (məsələn, özünü fayla saxlamaq və ya şəbəkə ilə göndərmək üçün) və sonra yenidən bərpa olunması bacarığıdır. Tutaq ki, oyununuzun vəziyyətini saxlamaq və ya obyekti serverə göndərmək istəyirsiniz — seriyalaşdırma olmadan alınmayacaq.

Java-da bunun üçün marker interfeys Serializable var. Marker — o deməkdir ki, bu interfeys metodlar ehtiva etmir, sadəcə sinfi seriyalaşdırıla bilən kimi “işarələyir”.

import java.io.Serializable;

public class Student implements Serializable {
    private String name;
    private int age;

    // ... qalan kod
}

Obyekti necə seriyalaşdırmalı

Seriyalaşdırma və deserializasiya üçün ObjectOutputStreamObjectInputStream siniflərindən istifadə olunur. Nümunə — obyekti fayla saxlayırıq və geri oxuyuruq:

import java.io.*;

public class Main {
    public static void main(String[] args) throws Exception {
        Student s = new Student("Katya", 19);

        // Obyekti fayla saxlayırıq
        try (ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("student.dat"))) {
            out.writeObject(s);
        }

        // Obyekti fayldan oxuyuruq
        try (ObjectInputStream in = new ObjectInputStream(new FileInputStream("student.dat"))) {
            Student loaded = (Student) in.readObject();
            System.out.println("Yükləndi: " + loaded);
        }
    }
}

Qeyd: Obyektin (və iç içə obyektlərin) bütün sahələri də seriyalaşdırıla bilən olmalıdır, əks halda xəta baş verəcək.

Marker interfeys nə üçündür

Serializable interfeysi metodların reallaşdırılmasını tələb etmir — o, sadəcə JVM-ə bildirir: “bu obyekti seriyalaşdırmaq olar”. Əgər onu reallaşdırmağı unutmusunuzsa, seriyalaşdırma cəhdi NotSerializableException istisnası ilə nəticələnəcək.

3. Standart kitabxananın digər vacib interfeysləri

Interfeys Cloneable

Daha bir marker interfeys. Onun vəzifəsi JVM-ə başa salmaqdır ki, obyekti klonlamaq olar — Object.clone() metodu ilə. Onsuz clone() çağırışı istisna atacaq.

Lakin Java-da klonlama — incə mövzudur. Susmaya görə klonlama səthidir (shallow copy) və çox vaxt bunun əvəzinə özünüz dərin nüsxələmə edən metodlar yazmaq daha yaxşıdır.

public class Student implements Cloneable {
    private String name;
    private int age;

    @Override
    public Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}

Interfeys AutoCloseable

Bu interfeys cəmi bir close() metodunu ehtiva edir. Onu reallaşdıran istənilən sinfi try-with-resources konstruksiyasında istifadə etmək olar — resursların avtomatik bağlanması (məsələn, fayllar, axınlar):

public class MyResource implements AutoCloseable {
    @Override
    public void close() {
        System.out.println("Resurs bağlandı!");
    }
}

public class Main {
    public static void main(String[] args) {
        try (MyResource res = new MyResource()) {
            System.out.println("Resursla işləyirik");
        }
        // Burada res.close() avtomatik çağırılacaq
    }
}

Interfeys Iterable<T>

Bu interfeys obyektinizin for-each dövründə “keçirilə” bilməsinə imkan verir. Cəmi bir iterator() metodu var və o, Iterator<T> obyektini qaytarır.

public class MyList implements Iterable<String> {
    // ... daxili saxlayıcı

    @Override
    public java.util.Iterator<String> iterator() {
        // Elementləri keçmək üçün iterator qaytarırıq
        return ...;
    }
}

Bütün standart kolleksiyalar (ArrayList, HashSet və s.) Iterable-i reallaşdırır, buna görə də onları for-each ilə keçmək olar.

Interfeys Comparator<T>

Bu interfeys obyektləri müxtəlif qaydalar üzrə müqayisə etməyə imkan verir, obyektlərin özlərini dəyişmədən. Məsələn, tələbələri yaşa görə deyil, ada görə sıralamaq.

import java.util.Comparator;

Comparator<Student> byName = new Comparator<Student>() {
    @Override
    public int compare(Student a, Student b) {
        return a.getName().compareTo(b.getName());
    }
};

Müasir Java-da bu, adətən lambda ifadələri ilə edilir:

Comparator<Student> byName = (a, b) -> a.getName().compareTo(b.getName());

Observer, EventListener

Bu interfeyslər “müşahidəçi” və “hadisə dinləyicisi” pattern-lərini qurmaq üçün istifadə olunur — bir obyekt digərində baş verən hadisələrə reaksiya verir. Məsələn, qrafik interfeyslərdə (Swing, JavaFX) düymə emalçıları ActionListener interfeysini reallaşdırır.

4. Təcrübə: Comparable reallaşdırırıq və obyekti seriyalaşdırırıq

Nümunə 1. Öz sinfiniz üçün Comparable

Gəlin, nəşr ilinə görə sıralana bilən Book sinfini yazaq:

public class Book implements Comparable<Book> {
    private String title;
    private int year;

    public Book(String title, int year) {
        this.title = title;
        this.year = year;
    }

    @Override
    public int compareTo(Book other) {
        return Integer.compare(this.year, other.year);
    }

    @Override
    public String toString() {
        return title + " (" + year + ")";
    }
}
import java.util.*;

public class Main {
    public static void main(String[] args) {
        List<Book> books = Arrays.asList(
            new Book("Java yeni başlayanlar üçün", 2018),
            new Book("Müharibə və sülh", 1869),
            new Book("Harri Potter", 1997)
        );
        Collections.sort(books);
        System.out.println(books);
    }
}

Nəticə:

[Müharibə və sülh (1869), Harri Potter (1997), Java yeni başlayanlar üçün (2018)]

Nümunə 2. Obyektin seriyalaşdırılması

import java.io.*;

public class Book implements Serializable {
    private String title;
    private int year;
    // ... konstruktor, getter-lər, toString

    public Book(String title, int year) {
        this.title = title;
        this.year = year;
    }

    @Override
    public String toString() {
        return title + " (" + year + ")";
    }
}

public class Main {
    public static void main(String[] args) throws Exception {
        Book book = new Book("Java yeni başlayanlar üçün", 2018);

        // Obyekti fayla saxlayırıq
        try (ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("book.dat"))) {
            out.writeObject(book);
        }

        // Obyekti fayldan oxuyuruq
        try (ObjectInputStream in = new ObjectInputStream(new FileInputStream("book.dat"))) {
            Book loaded = (Book) in.readObject();
            System.out.println("Yükləndi: " + loaded);
        }
    }
}

5. Cədvəl: standart kitabxananın əsas interfeysləri

Interfeys Təyinatı Açar metodlar İstifadə nümunəsi
Comparable<T>
Obyektlərin təbii sırası
int compareTo(T o)
Siyahıların sıralanması
Comparator<T>
Obyektlərin istifadəçi qaydaları ilə müqayisəsi
int compare(T a, T b)
Müxtəlif qaydalarla sıralama
Serializable
Obyektlərin seriyalaşdırılması — (marker) Obyektlərin saxlanması/yüklənməsi
Cloneable
Obyektlərin klonlanması — (marker) Obyekt nüsxələrinin yaradılması
AutoCloseable
Resursların avtomatik bağlanması
void close()
try-with-resources
Iterable<T>
Kolleksiyalarda elementlərin üzərindən keçid
Iterator<T> iterator()
for-each dövrü
Observer / EventListener Hadisələrə reaksiya
update(), actionPerformed
UI-də hadisələrin emalı, pattern-lər

6. Standart interfeyslərlə işləyərkən tipik səhvlər

Səhv № 1: İnterfeys reallaşdırılmayıb, amma funksionallıq tələb olunur.
Məsələn, Serializable reallaşdırmağı unutmusunuz, amma obyekti seriyalaşdırmağa çalışırsınız — NotSerializableException alacaqsınız. Eyni hal Cloneableclone() çağırışı üçün də keçərlidir.

Səhv № 2: Comparable və equals müqaviləsinin pozulması.
Əgər a.compareTo(b) == 0, amma yerinə yetirilmir a.equals(b), kolleksiyalar qəribə davrana bilər. Məsələn, TreeSet obyektləri “itirə” bilər.

Səhv № 3: Klonlama zamanı səthi nüsxələmə.
clone() metodu susmaya görə yalnız obyektin “üst qatını” kopyalayır. Əgər digər obyektlərə istinad edən sahələriniz varsa, onlar dərindən kopyalanmır. Bu isə müəmmalı bug-lara səbəb ola bilər.

Səhv № 4: try-with-resources-dan istifadə etməmək.
Əgər sinif AutoCloseable-ı reallaşdırır, amma onu try-with-resources içində istifadə etmirsinizsə, resursu bağlamağı unutmaq riskiniz var — nəticədə yaddaş sızması və ya faylın bloklanması baş verə bilər.

Səhv № 5: compareTo və ya compare-in yanlış reallaşdırılması.
Yalnız 0 və ya 1 qaytarmaq (mənfi/sıfır/müsbət diapazonu əvəzinə) sıralamanın düzgün işləməməsinə səbəb olacaq.

1
Sorğu/viktorina
, səviyyə, dərs
Əlçatan deyil
İrəli səviyyəli interfeyslər
İrəli səviyyəli interfeyslər və funksional interfeyslər
Şərhlər
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION