CodeGym /Kurslar /JAVA 25 SELF /ObjectOutputStream, ObjectInputStream: axınlarla iş

ObjectOutputStream, ObjectInputStream: axınlarla iş

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

1. Giriş

Java-da sərializasiya yalnız bunu açıq şəkildə icazə verən obyektlərlə işləyir. Bunun üçün sinif xüsusi interfeysi — java.io.Serializable — reallaşdırmalıdır.

import java.io.Serializable;

public class Person implements Serializable {
    // Sahələr, konstruktorlar, metodlar
}

Serializable marker interfeysdir: onun metodları yoxdur, o sadəcə JVM-ə — «bu sinfi sərializasiya etmək olar, narahat olmayın!» — xəbər verir. Əgər Serializable reallaşdırmayan sinfin obyektini sərializasiya etməyə cəhd etsəniz, NotSerializableException alacaqsınız. Hətta ən azı bir sahə (və ya daxil edilmiş obyekt) sərializasiya oluna bilmirsə — sərializasiya işləməyəcək.

ObjectOutputStream və ObjectInputStream

  • ObjectOutputStream — obyektləri axına yazan sinifdir (məsələn, fayla və ya şəbəkə üzərindən).
  • ObjectInputStream — obyektləri axından oxuyan sinifdir.

Onlar cütlük kimi işləyir: biri obyekti sərializasiya edir, digəri — deserializasiya edir.

Əsas metodlar

  • writeObject(Object obj) — obyekti sərializasiya edir və onu axına yazır.
  • readObject() — obyekti axından oxuyur, deserializasiya edir və geri qaytarır.

Vacibdir: hər iki sinif adi giriş-çıxış axınlarının (OutputStream və InputStream) üzərində işləyir. Çox vaxt onları fayl axınları ilə — FileOutputStream və FileInputStream — birlikdə istifadə edirlər, lakin şəbəkə axınları ilə də tətbiq etmək olar.

2. Sərializasiya nümunəsi

Gəlin sadə bir nümunə yazaq: Person sinfinin obyektini sərializasiya edib deserializasiya edək.

Addım 1. Sinfi təsvir edirik

import java.io.Serializable;

public class Person implements Serializable {
    private String name;
    private int age;
    // transient sahə sərializasiya olunmayacaq
    private transient String secret;

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

    @Override
    public String toString() {
        return "Person{name='" + name + "', age=" + age + ", secret='" + secret + "'}";
    }
}

Addım 2. Obyektin fayla sərializasiyası

import java.io.FileOutputStream;
import java.io.ObjectOutputStream;

public class SerializeDemo {
    public static void main(String[] args) throws Exception {
        Person person = new Person("Alice", 30, "likes pizza");

        // Fayla yazmaq üçün axın yaradırıq
        FileOutputStream fileOut = new FileOutputStream("person.bin");
        ObjectOutputStream out = new ObjectOutputStream(fileOut);

        // Obyekti saxlayırıq
        out.writeObject(person);

        // Axınları bağlayırıq
        out.close();
        fileOut.close();

        System.out.println("Obyekt person.bin faylına sərializasiya olundu");
    }
}

Addım 3. Obyektin fayldan deserializasiyası

import java.io.FileInputStream;
import java.io.ObjectInputStream;

public class DeserializeDemo {
    public static void main(String[] args) throws Exception {
        // Fayldan oxumaq üçün axını açırıq
        FileInputStream fileIn = new FileInputStream("person.bin");
        ObjectInputStream in = new ObjectInputStream(fileIn);

        // Obyekti bərpa edirik
        Person person = (Person) in.readObject();

        in.close();
        fileIn.close();

        System.out.println("Obyekt deserializasiya olundu: " + person);
    }
}

Gözlənilən çıxış

Obyekt person.bin faylına sərializasiya olundu
Obyekt deserializasiya olundu: Person{name='Alice', age=30, secret='null'}

Diqqət! transient sahə sərializasiya olunmur. Deserializasiyadan sonra onun dəyəri null olacaq. Bu, müvəqqəti və ya həssas məlumatlar üçün vacibdir.

3. Məhdudiyyətlər və özəlliklər

Bütün sahələr sərializasiya oluna bilən olmalıdır

Əgər sinifdə Serializable reallaşdırmayan sahələr (və ya belə obyektlər saxlayan sahələr) varsa, sərializasiya xəta ilə tamamlanacaq. Məsələn, Thread və ya Socket kimi tipləri «elə-belə» sərializasiya oluna bilən etmək mümkün deyil.

Statik və transient sahələr

  • Statik sahələr (static) sərializasiya olunmur: onlar konkret obyektə yox, sinifə məxsusdur.
  • transient sahələr — transient kimi işarələnmiş sahələr sərializasiyadan məqsədli şəkildə çıxarılır və bərpadan sonra standart dəyərləri alır (null, 0 və s.).

İstisnalar

  • Serializable reallaşdırmayan obyekti sərializasiya etmək cəhdi NotSerializableException yaradır.
  • Deserializasiya zamanı mümkün xətalar: fayl tapılmadı, siniflər uyğun gəlmir, məlumatlar zədələnib və s.

Siniflərin versiyaları

Əgər sərializasiyadan sonra sinifin strukturunu dəyişsəniz (məsələn, sahə əlavə/çıxarsanız), deserializasiya zamanı InvalidClassException yarana bilər. Versiyaya nəzarət üçün xüsusi serialVersionUID sahəsindən istifadə olunur (bu haqda növbəti mühazirələrdən birində daha ətraflı).

4. Təcrübə: obyektin fayla sərializasiyası və fayldan deserializasiyası

Tutaq ki, bizdə Person sinfi var və insanlar siyahısını fayla saxlamaq, sonra isə geri oxumaq istəyirik.

Person sinfi (sərializasiya oluna bilən)

import java.io.Serializable;

public class Person implements Serializable {
    private String name;
    private int age;
    private transient String secret; // sərializasiya olunmayacaq

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

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

İnsanlar siyahısının sərializasiyası

import java.io.FileOutputStream;
import java.io.ObjectOutputStream;
import java.util.ArrayList;
import java.util.List;

public class SerializeListDemo {
    public static void main(String[] args) throws Exception {
        List<Person> people = new ArrayList<>();
        people.add(new Person("Alice", 30, "likes pizza"));
        people.add(new Person("Bob", 25, "hates broccoli"));

        FileOutputStream fileOut = new FileOutputStream("people.bin");
        ObjectOutputStream out = new ObjectOutputStream(fileOut);

        // Siyahını saxlayırıq
        out.writeObject(people);

        out.close();
        fileOut.close();

        System.out.println("İnsanlar siyahısı sərializasiya olundu.");
    }
}

İnsanlar siyahısının deserializasiyası

import java.io.FileInputStream;
import java.io.ObjectInputStream;
import java.util.List;

public class DeserializeListDemo {
    public static void main(String[] args) throws Exception {
        FileInputStream fileIn = new FileInputStream("people.bin");
        ObjectInputStream in = new ObjectInputStream(fileIn);

        // Siyahını bərpa edirik
        List<Person> people = (List<Person>) in.readObject();

        in.close();
        fileIn.close();

        for (Person p : people) {
            System.out.println(p);
        }
    }
}

Nəticə:

Alice (30), secret: null
Bob (25), secret: null

5. Tipik səhvlər

Səhv №1: Sinif Serializable reallaşdırmır. Əgər implements Serializable əlavə etməyi unutsanız, sərializasiya zamanı NotSerializableException alacaqsınız. Bu, ən yayılmış və ən sadə səhvdir.

Səhv №2: Sərializasiya olunmayan sahə. Əgər obyekt sərializasiya oluna bilməyən bir sahə saxlayırsa (məsələn, Thread, Socket və ya Serializable olmayan istənilən başqa tip), sərializasiya «yıxılacaq». Belə sahələri transient kimi işarələyin və ya onları sərializasiya oluna bilən edin.

Səhv №3: Sinifin strukturunun dəyişdirilməsi. Əgər obyekt sərializasiya olunub, sonra isə sinif dəyişdirilibsə (sahələr əlavə/çıxarılıbsa), oxuma zamanı InvalidClassException mümkündür. Versiya sabitliyinə nəzarət üçün serialVersionUID göstərin.

Səhv №4: Statik sahələri sərializasiya etməyə cəhd. static modifikatorlu sahələr sərializasiya olunmur. Deserializasiyadan sonra onların dəyərləri, sərializasiya anındakı yox, sinifdəki standart dəyərlər olacaq.

Səhv №5: Axınlar bağlanmayıb. İşdən sonra axınları bağlamasanız, fayl zədələnə və ya resurs sızması yarana bilər. try-with-resources istifadə edin və ya axınları açıq şəkildə bağlayın.

Səhv №6: Siniflərin uyğun gəlməməsi. Əgər sinfin adı dəyişdirilibsə və ya başqa paketə köçürülübsə, deserializasiya işləməyəcək — axında saxlanmış sinfin adı və paketi ilə tam uyğunluq tələb olunur.

1
Tapşırıq
JAVA 25 SELF, səviyyə, dərs
Bağlanıb
Sadə obyektin seriyalaşdırılması
Sadə obyektin seriyalaşdırılması
1
Tapşırıq
JAVA 25 SELF, səviyyə, dərs
Bağlanıb
transient-sahə və seriyalaşdırma
transient-sahə və seriyalaşdırma
Şərhlər
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION