CodeGym /Kurslar /JAVA 25 SELF /Yuvalanmış obyektlərin seriyalaşdırılması: xüsusiyyətlər

Yuvalanmış obyektlərin seriyalaşdırılması: xüsusiyyətlər

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

1. Giriş: istinad sahələri olan obyektlərin seriyalaşdırılması

Həqiqi tətbiqlərdə tam “yastı” siniflər nadir hallarda rast gəlinir. Adətən obyekt başqa obyektlər saxlayır, onlar isə öz növbəsində yenə nələrisə saxlaya bilər. Bu, obyektlərin kompozisiyası (və ya yuvalanması) adlanır. Məsələn:

public class Address {
    String city;
    String street;
}

public class Person {
    String name;
    int age;
    Address address; // Yuvalanmış obyekt!
}

Belə bir obyekti seriyalaşdıranda sual yaranır: bəs address sahəsi ilə nə etməli? Java onu Person ilə birlikdə seriyalaşdırmalıdırmı? Bəs Address-in daxilində başqa bir obyekt varsa? Xoşbəxtlikdən (və ya bədbəxtlikdən — vəziyyətdən asılı olaraq), Java susmaya görə bütün yuvalanmış obyektləri rekursiv şəkildə seriyalaşdırır, əgər onlar da Serializable interfeysini reallaşdırırlarsa.

Java-da seriyalaşdırma — həmişə dərin seriyalaşdırmadır (deep serialization). Bu o deməkdir ki, təkcə obyektin özü deyil, onun ( transient olmayan) sahələri vasitəsilə istinad etdiyi bütün obyektlər və sair — ən “dibə” qədər seriyalaşdırılır.

Prosesin vizuallaşdırılması

graph TD
    A[Person] --> B[Address]
    B --> C[CityInfo]
    A --> D[Pet]

Bir sözlə, əgər Person-u seriyalaşdırmağa qərar verdinizsə, Java həm Address-i, həm də Address-in daxilində olan hər nə varsa hamısını seriyalaşdıracaq və s.

2. Tələblər: yuvalanmış obyektlər üçün Serializable mütləqdir!

Yəqin ki, artıq vacib bir nüansa fikir vermisiniz: seriyalaşdırılan bütün yuvalanmış obyektlər də mütləq Serializable interfeysini reallaşdırmalıdır.

Əgər ən azı bir istinad sahəsi Serializable-ı reallaşdırmayan obyektə işarə edirsə, seriyalaşdırma cəhdi java.io.NotSerializableException istisnası ilə başa çatacaq.

Gəlin dərin seriyalaşdırma nümunələrinə baxaq.

Nümunə: hər şey qaydasındadır

import java.io.Serializable;

public class Address implements Serializable {
    String city;
    String street;
}

public class Person implements Serializable {
    String name;
    int age;
    Address address;
}

Hər iki sinif Serializable-ı reallaşdırır. Hər şey işləyir, seriyalaşdırma uğurla keçir.

Nümunə: xəta!

public class Address { // Serializable REALLAŞDIRMIR!
    String city;
    String street;
}

public class Person implements Serializable {
    String name;
    int age;
    Address address;
}

Gördüyümüz kimi, burada Address Serializable interfeysini reallaşdırmır. Buna görə də Person-u seriyalaşdırarkən NotSerializableException istisnası alacağıq.

3. Nümunə: yuvalanmış obyektlə seriyalaşdırma və deseriyalaşdırma

Gəlin bunun praktikada necə göründüyünə baxaq. Ötən səviyyədə “Kontakt meneceri” tətbiqi ilə işləmişdik. Gəlin indi hər bir istifadəçinin ünvanını ora əlavə edək.

import java.io.*;

class Address implements Serializable {
    String city;
    String street;

    Address(String city, String street) {
        this.city = city;
        this.street = street;
    }
}

class Person implements Serializable {
    String name;
    int age;
    Address address;

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

public class SerializationDemo {
    public static void main(String[] args) throws Exception {
        Person p = new Person("İvan", 30, new Address("Praqa", "Slavinska, 1"));
        // Seriyalaşdırma
        ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("person.ser"));
        out.writeObject(p);
        out.close();

        // Deseriyalaşdırma
        ObjectInputStream in = new ObjectInputStream(new FileInputStream("person.ser"));
        Person restored = (Person) in.readObject();
        in.close();

        System.out.println(restored.name + ", " + restored.age + ", " +
                           restored.address.city + ", " + restored.address.street);
    }
}

Nəticə:

İvan, 30, Praqa, Slavinska, 1

Hər şey işləyir: yuvalanmış Address obyekti Person ilə birlikdə seriyalaşdırılıb və bərpa olunub.

4. Bəs yuvalanmış obyekt seriyalaşdırıla bilmirsə?

Əgər elə bir obyekti seriyalaşdırmağa çalışsanız ki, onun ən azı bir istinad sahəsi Serializable-ı reallaşdırmayan obyektə işarə edir, Java seriyalaşdırma cəhdi zamanı istisna atacaq.

Xətanın nümayişi

class Address { // Serializable deyil!
    String city;
    String street;
}

class Person implements Serializable {
    String name;
    Address address;
}

public class Test {
    public static void main(String[] args) throws Exception {
        Person p = new Person();
        p.name = "Petya";
        p.address = new Address();
        p.address.city = "Derri";
        p.address.street = "Vyazov";
        ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("person.ser"));
        out.writeObject(p); // <-- İSTİSNA ATILACAQ!
        out.close();
    }
}

Xəta:

java.io.NotSerializableException: Address

5. Yuvalanmış obyektlər üçün transient

Nə etmək olar, əgər sizdə seriyalaşdırılmamalı olan bir obyektə istinad edən sahə varsa (məsələn, keş, verilənlər bazası bağlantısı, müvəqqəti obyekt)? Belə halda sahəni transient kimi elan edin. O zaman Java seriyalaşdırma zamanı bu sahəni sadəcə ötürəcək.

Transient ilə nümunə

class Address { // Serializable deyil
    String city;
    String street;
}

class Person implements Serializable {
    String name;
    transient Address address; // transient!

    Person(String name, Address address) {
        this.name = name;
        this.address = address;
    }
}

public class Test {
    public static void main(String[] args) throws Exception {
        Address addr = new Address();
        addr.city = "Los-Santos";
        addr.street = "Mulholland Drive";
        Person p = new Person("Saşa", addr);

        ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("person.ser"));
        out.writeObject(p);
        out.close();

        // Deseriyalaşdırma
        ObjectInputStream in = new ObjectInputStream(new FileInputStream("person.ser"));
        Person restored = (Person) in.readObject();
        in.close();

        System.out.println(restored.name); // "Saşa"
        System.out.println(restored.address); // null!
    }
}

Nəticə:
address sahəsi deseriyalaşdırmadan sonra null-a bərabərdir, çünki o, transient-dir.

6. Dərin yuvalanma və rekursiya

Seriyalaşdırma rekursiv işləyir: əgər Person-da Address sahəsi varsa, Address-də isə CityInfo sahəsi və sair, seriyalaşdırıcı “daha dərinə” dalacaq, ta ki, seriyalaşdırıla bilməyən nəsə tapılana və ya yaddaş bitənə qədər (zarafatdır, amma yarı ciddi).

Vacibdir: dövrü istinadlar

Java seriyalaşdırıcısı dövrü istinadlarla işləməyi bacarır. Məsələn, obyekt başqa bir obyektə, o isə geri birincisinə istinad edirsə, seriyalaşdırıcı sonsuz dövrə düşməyəcək, strukturu səliqə ilə saxlayacaq.

class A implements Serializable {
    B b;
}
class B implements Serializable {
    A a;
}

Əgər biri-birinə istinad edən AB obyektlərini yaratsanız, seriyalaşdırma StackOverflowError verməyəcək — Java artıq seriyalaşdırılmış obyektləri yadda saxlayır.

7. Nümunə: yuvalanmış siyahısı olan obyektin seriyalaşdırılması

Çox vaxt obyektin daxilində digər obyektlərin kolleksiyaları olur. Məsələn, istifadəçinin dostlar siyahısı ola bilər:

import java.io.*;
import java.util.*;

class Person implements Serializable {
    String name;
    List<Person> friends;

    Person(String name) {
        this.name = name;
        this.friends = new ArrayList<>();
    }
}

public class FriendsSerialization {
    public static void main(String[] args) throws Exception {
        Person alice = new Person("Alice");
        Person bob = new Person("Bob");
        alice.friends.add(bob);

        // Seriyalaşdırma
        ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("friends.ser"));
        out.writeObject(alice);
        out.close();

        // Deseriyalaşdırma
        ObjectInputStream in = new ObjectInputStream(new FileInputStream("friends.ser"));
        Person restored = (Person) in.readObject();
        in.close();

        System.out.println(restored.name); // Alice
        System.out.println(restored.friends.get(0).name); // Bob
    }
}

Vacibdir: Java-nın standart kitabxanasındakı kolleksiyalar (ArrayList, HashMap və s.) Serializable-ı reallaşdırır, yəni hər şey standart olaraq işləyir.

8. Yuvalanmış obyektlərin seriyalaşdırılmasında tipik səhvlər

Xəta №1: Yuvalanmış obyektlərdən biri Serializable reallaşdırmır. Zəncirinizdəki siniflərdən birinə implements Serializable əlavə etməyi unutmusanız. Nəticə — ilk seriyalaşdırma cəhdində NotSerializableException. Seriyalaşdırma zəncirinizdəki bütün siniflərin bu interfeysi dəstəklədiyini yoxlayın.

Xəta №2: Seriyalaşdırılmayan sahə transient kimi elan edilməyib. Əgər seriyalaşdırılmayan sahəniz varsa (məsələn, axın, verilənlər bazası bağlantısı, müvəqqəti nəsə), amma onu transient kimi elan etməmisinizsə, seriyalaşdırma səhvlə nəticələnəcək. transient-i unutmayın!

Xəta №3: Daxili siniflərdə serialVersionUID uyğunsuzluğu. Əgər yuvalanmış siniflərdə serialVersionUID-i açıq elan edir və onların strukturunu dəyişirsinizsə, bu identifikatoru yeniləməyi unutmayın — əks halda deseriyalaşdırma zamanı səhvlər mümkündür.

Xəta №4: Mutasiya olunan (dəyişən) yuvalanmış obyektlər. Əgər sonradan dəyişən kolleksiyanı və ya obyekti seriyalaşdırırsınızsa (məsələn, dostlar siyahısı), deseriyalaşdırmadan sonra bu artıq seriyalaşdırma anının “snapshot”u olacaq. Orijinaldakı yeni dəyişikliklər deseriyalaşdırılmış obyektə təsir etməyəcək.

Xəta №5: Çox böyük obyekt qraflarını seriyalaşdırmaq. Əgər çoxlu yuvalanmış obyektləri olan mürəkkəb bir strukturunuz varsa, seriyalaşdırma çox vaxt və yaddaş tuta bilər. Bəzən bütün strukturu deyil, yalnız əsas məlumatları seriyalaşdırmaq daha məqsədəuyğundur.

1
Tapşırıq
JAVA 25 SELF, səviyyə, dərs
Bağlanıb
Rəqəmsal şəxsi məlumatlar kartotekası 🏢
Rəqəmsal şəxsi məlumatlar kartotekası 🏢
1
Tapşırıq
JAVA 25 SELF, səviyyə, dərs
Bağlanıb
Çətin çatdırılma logistikasının idarə edilməsi: dərin iç-içə məlumatlar 🌍
Çətin çatdırılma logistikasının idarə edilməsi: dərin iç-içə məlumatlar 🌍
Şərhlər
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION