Java Records - bu Java 14 da oldindan ko'rish funksiyasi sifatida kiritilgan va keyinroq yakunlangan xususiyat bo'lib, asosan ma'lumotlarni saqlash uchun ishlatiladigan sinflarni e'lon qilishning qisqa va qulay usulini taqdim etadi. Ular ma'lumotlar maydonlarini, konstruktorlarni, qo'shimcha qurilmalarni va boshqa keng tarqalgan usullarni inkapsulyatsiya qilish uchun kerakli kodni avtomatik ravishda yaratish orqali o'zgarmas sinflarni yaratishni soddalashtirish uchun mo'ljallangan.

Java Records-ni joriy etishning asosiy motivlari quyidagilardir:

Qisqalik: Yozuvlar maydonga kirish moslamalari, equals(), hashCode() va toString() usullari kabi umumiy vazifalar uchun standart ilovalarni avtomatik tarzda yaratish orqali standart kodni kamaytiradi. Bu ishlab chiquvchilarga maʼlumotlar maydonlari va ularning xatti-harakatlarini aniqlashga eʼtibor qaratish imkonini beradi.

O'zgarmaslik: Yozuvlar sukut bo'yicha o'zgarmas bo'lishi uchun yaratilgan, ya'ni ob'ekt yaratilgandan keyin uning holatini o'zgartirib bo'lmaydi. Bu xususiyat maʼlumotlar yaxlitligi va izchilligi muhim boʻlgan koʻpgina stsenariylarda maʼqul boʻladi.

O'qilishi: Yozuvlardan foydalanish orqali kodning maqsadi aniqroq bo'ladi. Yozuvlar sinf asosan maʼlum maydonlar toʻplamiga ega maʼlumotlar konteyneri ekanligini aniq bildiradi.

Namunani moslashtirish: Java yozuvlari Java 14-da taqdim etilgan naqsh moslashtirish funksiyasi bilan yaxshi ishlaydi. Ulardan maʼlumotlarni ajratib olish va taqqoslashni oʻz ichiga olgan kodni soddalashtirish uchun naqsh sifatida foydalanish mumkin.

Yozuvlarni qanday yaratish kerak?

Keling, o'zgarmas sinf yarataylik:

public final class Account {

    private final String name;
    private final int id;
    private final String type;

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

    public String name() {
        return name;
    }

    public int id() {
        return id;
    }

    public String type() {
        return type;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Account that = (Account) o;
        return id == that.id && Objects.equals(name, that.name) && Objects.equals(type, that.type);
    }

    @Override
    public int hashCode() {
        return Objects.hash(name, id, type);
    }

   @Override
    public String toString() {
        return "Account{" +
                "name='" + name + '\'' +
                ", id=" + id +
                ", type='" + type + '\'' +
                '}';
    }
}

Endi yozuv yordamida bir xil o'zgarmas sinfni yaratamiz. Java-da rekord sinf yaratish uchun record kalit so'zidan foydalanishimiz kerak. Konstruktorlarda bo'lgani kabi, atributlar va ularning turlarini yozuvda eslatib o'tishimiz kerak. Berilgan misolda Hisob yozuv turi bo‘lib, hisob ma’lumotlarini saqlash uchun ishlatiladi:

public record Account(String name, int id, String type) {}

Ko'rib turganimizdek, biz bitta kod satri bilan to'liq sinfni qisqartirishimiz mumkin. Biz record kalit so'zini ishlatish uchun class kalit so'zini almashtirdik va soddalik sehriga yo'l qo'ydik.

Java'dagi record kalit so'zi avtomatik ravishda biz uchun konstruktor, getters, equals(), hashCode() va toString() kabi bir nechta usullarni yaratadi. Ushbu usullar rekord sinf ob'ektlarini qulay tarzda yaratish va boshqarish uchun ishlatiladi. Masalan, Account yozuvini aniqlagandan so'ng, biz Account sinfining misolini quyidagicha yaratishimiz mumkin:

Account account = new Account("John Doe", 123456, "Savings");

Bu name, id va type maydonlari uchun belgilangan qiymatlarga ega yangi Account ob'ektini yaratadi. Bu rekord bo'lgani uchun biz hosil qilingan getter usullaridan foydalangan holda maydonlarga to'g'ridan-to'g'ri kirishimiz mumkin. Masalan; misol uchun:

String accountName = account.name();
int accountId = account.id();
String accountType = account.type();

System.out.println(accountName);
System.out.println(accountId);
System.out.println(accountType); 

// Output

John Doe
123456
Savings

Muhim nuqtalar:

  1. Biz Record sinfini aniq kengaytira olmaymiz

Garchi barcha yozuvlar java.lang.Record sinfini kengaytirsa ham, biz hali ham java.lang.Record kichik sinfini aniq yarata olmaymiz. Kompilyator orqali o'tmaydi. Bu shuni anglatadiki, yozuvni olishning yagona yo'li uni aniq e'lon qilishdir.

final class Account extends Record {   
// Compiler error : The type Data may not subclass Record explicitly
	private final int id;
}

2. Interfeyslarni amalga oshirish

Yozuv sinflari interfeyslarni amalga oshirishga imkon beradi. Biz xohlagan interfeysni amalga oshirishimiz mumkin, xoh u bitta interfeys yoki bir nechta interfeys.

public record Account( int id, String name) implements Runnable, Serializable

3. O'z misol o'zgaruvchilarimizni aniqlay olmaymiz

Sarlavhani aniqlaganimizda, u yozuv sinfining holatini ifodalaydi. Bu shuni anglatadiki, bizda yozuv ichida boshqa misol o'zgaruvchisi bo'lishi mumkin emas. Yaratilishi mumkin bo'lgan yagona misol o'zgaruvchisi sarlavha komponentida taqdim etilgan o'zgaruvchidir. Biroq, biz yozuvlar sinfi nomidan foydalanib, sinflar kabi kirish mumkin bo'lgan statik o'zgaruvchilarga ega bo'lishimiz mumkin.

4. Bir nechta konstruktorlar

Java Record turi ta'rifi bir nechta konstruktorlarni o'z ichiga olishi mumkin. Hisob qaydnomasi turi uchun qo'shimcha konstruktorni belgilaydigan Java Record misoli:

public record Account( int id, String name) {
     public Account(int id) {
        this(id, null);
    }
}

Qo'shimcha konstruktor Hisob qaydnomasi deklaratsiyasining asosiy qismida e'lon qilinadi. Qo'shimcha konstruktor Hisob qaydnomasining standart konstruktorini qanday chaqirganiga e'tibor bering. Bu Java kompilyatori tomonidan talab qilinadi, shuning uchun kompilyator qo'shimcha konstruktordagi qaysi konstruktor parametrlari standart konstruktordagi qaysi parametrlarga mos kelishini biladi.

Biz aniq Java Record ta'rifimiz uchun qanchalik mantiqiy bo'lsa, shuncha qo'shimcha konstruktorlarni qo'shishimiz mumkin.

5. Namuna usullari

Biz Java Record ta'rifiga misol usullarini qo'shishimiz mumkin - xuddi oddiy Java sinfida bo'lgani kabi. Mana, nameAsUpperCase() nomli misol usuli qoʻshilgan oldingi boʻlimlardan Hisob Java Record taʼrifiga misol:

public record Account( int id, String name) {

    public static String nameAsUpperCase() {
        return name().toUpperCase();
    }
}

nameAsUperCase() usuli avtomatik ravishda yaratilgan name() usulini ichki qanday chaqirishiga e'tibor bering.

6. Statik usullar

Java Record ta'rifiga statik usullarni qo'shish ham mumkin. Mana bir misol:

public record Account( int id, String name) {

public static String nameAsUpperCase(Account acc) {
        return acc.name.toUpperCase();
    }
}

7. Izohlardan foydalanish

Yozuv komponentlariga izohlar qo'shishimiz mumkin. Masalan, @Transient izohini id maydoniga qo'llashimiz mumkin.

public record Account(@Transient Long id,String name, String type) 
            { // ... }

8. Seriyalashtirish va seriyadan chiqarish

Java tilidagi yozuvlarniseriyalashtirish oddiy sinflardan farq qiladi. Yozuv ob'ekti ketma-ketlashtirilganda, uning ketma-ketlashtirilgan shakli ob'ektning yakuniy misol maydonlaridan olingan qiymatlar ketma-ketligidan iborat. Yozuv obyektining oqim formati oqimdagi oddiy obyektniki bilan bir xil bo‘lib qoladi.

Deserializatsiya paytida, agar taqdim etilgan oqim sinfi deskriptoriga mos keladigan mahalliy sinf rekord sinf bo'lsa, oqim maydonlari yozuv komponentlari qiymatlarini ifodalash uchun o'qiladi va qayta tuziladi. Keyinchalik, yozuvning kanonik konstruktorini komponent qiymatlari argument sifatida chaqirish orqali yozuv ob'ekti yaratiladi. Agar oqimda komponent qiymati etishmayotgan bo‘lsa, komponent turi uchun standart qiymatdan foydalaniladi.

Odatiy bo'lib, agar aniq e'lon qilinmasa, yozuvlar sinfining serialVersionUID 0L ni tashkil qiladi. Rekord sinflari uchun serialVersionUID qiymatlarini moslashtirish talabi ham bekor qilinadi. Yozuv ob'ektlarini ketma-ketlashtirish jarayonini moslashtirib bo'lmaydi. Yozuv sinflarida belgilangan writeObject, readObject, readObjectNoData, readResolve, writeExternal va readExternal kabi har qanday sinfga xos usullar ketma-ketlashtirish va seriyadan chiqarish vaqtida e'tiborga olinmaydi. Biroq, writeReplace usuli ketma-ketlashtirish uchun muqobil ob'ektni qaytarish uchun ishlatilishi mumkin.

Har qanday ketma-ketlashtirish yoki seriyadan chiqarishni amalga oshirishdan oldin, biz yozuvni seriyali yoki tashqi ko'rinishga ega bo'lishi kerakligiga ishonch hosil qilishimiz kerak.

public record Account (...) implements Serializable { }

Xulosa

Java-dagi yozuv turlari juda foydali xususiyat bo'lib, har qanday Java-ga asoslangan tizimga qimmatli qo'shimcha bo'lib xizmat qiladi. Yozuvlarni qabul qilish orqali ko'plab ilovalar domen sinflarining ravshanligi va ixchamligini oshirishi mumkin. Bundan tashqari, jamoalar asosiy naqshni qo'lda ishlab chiqarishga bo'lgan talabni yo'q qilishlari va Lombok kabi kutubxonalarga bog'liqligini kamaytirishlari yoki yo'q qilishlari mumkin.

Baxtli o'rganish !!