CodeGym /Kurslar /JAVA 25 SELF /record və class arasındakı fərqlər, record məhdudiyyətlər...

record və class arasındakı fərqlər, record məhdudiyyətləri

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

1. record və class müqayisəsi: əsas fərqlər nələrdir?

Java-da məlumat tiplərini təsvir etməyin iki əsas yolu var: adi siniflər (class) və record sinifləri (record). İlk baxışda hər iki yanaşma məlumatları saxlamağa və emal etməyə imkan verir. Amma bir az dərinə getsək, fərqlərin göründüyündən daha çox olduğunu görəcəyik!

Fərqlər cədvəli: class vs record

Xüsusiyyət Adi sinif (class) Record sinfi (record)
Dəyişkənlik İstənilən: sahələri final etmək də olar, etməmək də Dəyişməz: bütün sahələr final
İrsiyyət İrs almaq olar (extends), susmaya görə final deyil Həmişə final, superklass ola bilməz
Sahələr İstənilən: statik, qeyri-statik, final və ya qeyri-final, istənilən tiplər Yalnız record komponentləri (private final), üstəlik statik sahələr
Getter/setter-lər Özümüz yazırıq (və ya Lombok ilə generasiya edirik) Getter-lər avtomatik yaradılır (sahənin adı metodun adı olur), setter yoxdur
equals/hashCode/toString Adətən əl ilə yazırıq/generasiya edirik (equals, hashCode, toString) Bütün komponentlər üzrə avtomatik generasiya olunur
Konstruktorlar İstənilən, say məhdudiyyəti yoxdur Bir əsas (bütün komponentlər üzrə), kompakt konstruktor əlavə etmək olar
İnterfeyslər Reallaşdırmaq olar Reallaşdırmaq olar
Əlavə metodlar İstənilən Əlavə etmək olar, amma yalnız metodlar (sahələr yox)
Kolleksiyalarda istifadə Olar, amma equals/hashCode düzgün reallaşdırılmalıdır Açarlar/dəyərlər üçün ideal, hər şey artıq reallaşdırılıb

Aydınlıq üçün nümunə

Adi sinif:


public class Person {
    private final String name;
    private final int age;

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

    public String getName() { return name; }
    public int getAge() { return age; }

    @Override
    public boolean equals(Object o) { /* ... */ }
    @Override
    public int hashCode() { /* ... */ }
    @Override
    public String toString() { /* ... */ }
}

Record sinfi:


public record Person(String name, int age) { }

Vəssalam! Bir sətir kod — və eyni nəticəni (hətta daha yaxşısını) alırıq. Və vacib nəyisə reallaşdırmağı unutmaq riski yoxdur.

2. record siniflərinin məhdudiyyətləri

Record sinifləri sadəcə “qısa sintaksis” deyil, öz sərt qaydaları olan ayrıca bir konsepsiyadır. Gəlin onları daha ətraflı nəzərdən keçirək.

Record həmişə final-dır

Tərifə görə record sinfi həmişə final-dır. Bu o deməkdir ki, siz record-dan subklass yarada bilməzsiniz:


public record Point(int x, int y) { }

// public class ColoredPoint extends Point { } // Kompilyasiya xətası!

Davranışı genişləndirmək lazımdırsa, adi siniflərdən və ya kompozisiyadan istifadə edin (record-u sinifin içinə daxil edin).

Record superklass ola bilməz

Record sinfi digər siniflər üçün valideyn ola bilməz, o həmişə final-dır. Bu məntiqlidir: əgər bu mümkün olsaydı, kimsə dəyişən sahə əlavə edə bilərdi — və “dəyişməz məlumatlar” konsepsiyası dağılardı.

Yalnız final sahələr (komponentlər)

Bütün record komponentləri başlıqda elan olunur və susmaya görə private final-dır. record-un gövdəsinə qeyri-statik sahə əlavə edə bilməzsiniz:


public record User(String login, String email) {
    // int counter; // Xəta! Qeyri-statik sahələr əlavə etmək olmaz
    static int totalUsers = 0; // Olar, bu statik sahədir
}

Setter-lər yoxdur

Record sinfinin komponentləri üçün setter-lər ola bilməz. setX(int x) kimi metod əlavə etmək cəhdi mənasızdır: obyekt yaradıldıqdan sonra sahənin dəyərini dəyişə bilməyəcəksiniz.


public record Point(int x, int y) {
    // public void setX(int x) { this.x = x; } // Xəta: final sahəni dəyişmək olmaz
}

Boş konstruktor yoxdur

record-sinifdə həmişə yalnız əsas konstruktor var, o da bütün komponentlər üçün dəyərləri qəbul edir. Bütün məlumatlar göstərilmədən record yaratmaq olmaz:


Point p = new Point(1, 2);  // OK
// Point p = new Point();   // Xəta: parametrsiz konstruktor yoxdur

Qeyri-statik init-bloklar yoxdur

Record sinfi qeyri-statik inisializator blokları (metodlardan kənar, fiqurlu mötərizələrdə yazılan) tuta bilməz:


public record User(String login) {
    // { /* ... */ } // Xəta: qeyri-statik inisializatorlar qadağandır
}

İrsiyyət üzrə məhdudiyyətlər

Record sinfi açıq şəkildə başqa sinfi miras ala bilməz (bütün record-lar üçün gizli baza sinfi olan java.lang.Record istisnadır). Amma interfeysləri reallaşdırmaq — buyurun!


public interface Printable {
    void print();
}

public record Book(String title) implements Printable {
    @Override
    public void print() {
        System.out.println("Kitabı çap edirik: " + title);
    }
}

Mürəkkəb biznes məntiqi üçün uyğun deyil

record — məlumat üçündür, davranış üçün yox. Obyektinizin mürəkkəb məntiqi, dəyişən vəziyyəti, “həyat dövrü” və ya çoxlu asılılıqları varsa — record kömək etməyəcək. Daha yaxşısı adi sinifdən istifadə etməkdir.

3. record siniflərini nə vaxt istifadə etməli?

  • DTO (Data Transfer Object): tətbiqin qatları, servislər, mikroservislər və ya REST nəzarətçiləri arasında dəyişməz məlumatları ötürmək üçün (məsələn, JSON cavablarında).
  • Value Object: yalnız dəyərləri ilə müəyyən olunan obyektlər.
  • Kolleksiyalarda açarlar və dəyərlər: equals və hashCode-un düzgün reallaşdırılması vacib olduqda (məsələn, HashMap və ya Set üçün).
  • Hesablama nəticələri: metoddən bir neçə dəyəri birdən qaytarmaq lazım olduqda (məsələn, record Pair<T, U>(T first, U second)).

Nümunə: REST nəzarətçisi üçün DTO


public record UserDto(String login, String email) { }

İndi bu tipdən olan obyekti nəzarətçidən rahatlıqla qaytara bilərsiniz — kimsənin onun sahələrini dəyişəcəyindən narahat olmayaraq.

Nümunə: HashMap üçün açar


public record Point(int x, int y) { }

Map<Point, String> pointNames = new HashMap<>();
pointNames.put(new Point(1, 2), "A");
pointNames.put(new Point(3, 4), "B");

// Hər şey düzgün işləyir: equals və hashCode artıq reallaşdırılıb!

4. record siniflərindən nə vaxt İSTİFADƏ ETMƏMƏK lazımdır

  • Dəyişən vəziyyət: obyekt yaradıldıqdan sonra azı bir sahə dəyişməlidirsə.
  • Mürəkkəb məntiq: obyektin davranışı mürəkkəbdirsə, çoxlu metodları və dəyişən vəziyyətli iç-içə obyektləri varsa.
  • İrsiyyət: sinif iyerarxiyası, abstrakt baza sinifləri, metodların yenidən yazılması tələb olunursa.
  • Biznes-məntiq entitiləri: məsələn, verilənlər bazasında “yaşayan” və unikal identifikatora malik obyektlər.

Nümunə: nə vaxt adi sinif lazımdır


public class Account {
    private String id;
    private int balance;

    public Account(String id, int balance) {
        this.id = id;
        this.balance = balance;
    }

    public void deposit(int amount) { balance += amount; }
    public void withdraw(int amount) { balance -= amount; }
    // getters, setters, equals, hashCode, toString...
}

Burada obyektin vəziyyətinin dəyişdiyi aydın görünür — record uyğun deyil.

5. Praktik nümunələr: record və class arasında seçim

Nümunə 1: record — ideal seçim


public record Rectangle(int width, int height) {
    public int area() {
        return width * height;
    }
}
  • Düzbucaqlı yalnız en və hündürlük ilə müəyyən olunur.
  • Yaradıldıqdan sonra bu dəyərləri dəyişməyə ehtiyac yoxdur.
  • Faydalı area() metodunu əlavə etmək olar.
  • Qalan hər şeyi Java sizin üçün edəcək.

Nümunə 2: class — ən yaxşı seçim


public class MutableRectangle {
    private int width;
    private int height;

    public MutableRectangle(int width, int height) {
        this.width = width;
        this.height = height;
    }

    public void setWidth(int width) { this.width = width; }
    public void setHeight(int height) { this.height = height; }

    public int area() { return width * height; }
}

Düzbucaqlının ölçülərini yaradıldıqdan sonra dəyişmək lazımdır? Adi sinifdən istifadə edin.

6. record sinifləri ilə işləyərkən tipik səhvlər

Səhv №1: qeyri-statik sahə əlavə etmək cəhdi.
Record sinfi komponentlər siyahısından kənarda qeyri-statik sahələr elan etməyə imkan vermir. Belə cəhd etsəniz — kompilyator xəta verəcək. Məsələn:


public record City(String name) {
    // int population; // Xəta!
}

Səhv №2: setter əlavə etmək istəyi.
Record komponentlər üçün setter-ləri dəstəkləmir. Obyekt yaradıldıqdan sonra sahənin dəyərini dəyişmək cəhdi — kompilyasiya səhvidir.

Səhv №3: record-u miras almaq və ya record-dan miras almağa cəhd.
Record həmişə final-dır. record-dan miras almaq olmaz və record başqa sinfi miras ala bilməz (gizli java.lang.Record istisna olmaqla).

Səhv №4: dəyişən (mutable) obyektlər üçün record istifadə etmək.
Obyektin vəziyyətini yaratdıqdan sonra dəyişməyi planlaşdırırsınızsa — record sizin üçün deyil! Adi sinifdən istifadə edin.

Səhv №5: konstruktor məhdudiyyətlərini unutmaq.
Record sinfində mütləq bütün komponentləri qəbul edən konstruktor olmalıdır. Parametrsiz konstruktor yoxdur!

1
Tapşırıq
JAVA 25 SELF, səviyyə, dərs
Bağlanıb
Daxilində ünvanı olan şirkət kartı 🏢
Daxilində ünvanı olan şirkət kartı 🏢
1
Tapşırıq
JAVA 25 SELF, səviyyə, dərs
Bağlanıb
Xəritədə koordinatların uyğunluğunu yoxlama 🗺️
Xəritədə koordinatların uyğunluğunu yoxlama 🗺️
1
Tapşırıq
JAVA 25 SELF, səviyyə, dərs
Bağlanıb
Sənədin məzmununun çapı 📄
Sənədin məzmununun çapı 📄
1
Tapşırıq
JAVA 25 SELF, səviyyə, dərs
Bağlanıb
Dəyişən və dəyişməyən istifadəçi profillərinin müqayisəsi 🧑‍🤝‍🧑
Dəyişən və dəyişməyən istifadəçi profillərinin müqayisəsi 🧑‍🤝‍🧑
1
Sorğu/viktorina
, səviyyə, dərs
Əlçatan deyil
Record-siniflər
Record-siniflər
Şərhlər
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION