1. Kolleksiyaların serializasiyası
Yaxşı xəbər: demək olar ki, bütün standart Java kolleksiyaları (məsələn, ArrayList, HashSet, HashMap və onların «dostları») artıq Serializable-ı implement edir. Bu o deməkdir ki, onları «qutudan çıxan kimi», əlavə mürəkkəbliyə ehtiyac olmadan serializasiya edə bilərsiniz.
Nümunə:
import java.io.Serializable;
import java.util.ArrayList;
public class MyList extends ArrayList<String> implements Serializable {
// Heç nə yazmaya da bilərsiniz — ArrayList artıq Serializable-dir!
}
Praktikada siz adətən standart kolleksiyaları serializasiya edirsiniz və hər şey artıq əziyyət olmadan işləyir.
Kolleksiyanı necə serializasiya etmək?
Kolleksiyanın serializasiyası istənilən digər obyekt kimi eyni yanaşma ilə edilir:
- Kolleksiya yaradırıq.
- Onu ObjectOutputStream vasitəsilə fayla yazırıq.
- ObjectInputStream ilə geri oxuyuruq.
Nümunə 1: Serializasiya ArrayList<String>
import java.io.*;
import java.util.*;
public class SerializeListDemo {
public static void main(String[] args) throws Exception {
// 1. Sətir siyahısı yaradırıq
List<String> books = new ArrayList<>();
books.add("Çovdarlıqda uçurum kənarında");
books.add("Böyük ümidlər");
books.add("İlahi komediya");
// 2. Siyahını fayla yazırıq
ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("books.ser"));
out.writeObject(books);
out.close();
// 3. Siyahını fayldan geri oxuyuruq
ObjectInputStream in = new ObjectInputStream(new FileInputStream("books.ser"));
List<String> loadedBooks = (List<String>) in.readObject();
in.close();
// 4. Nəticəni yoxlayırıq
System.out.println("Deserializasiyadan sonra kitab siyahısı:");
for (String book : loadedBooks) {
System.out.println("- " + book);
}
}
}
Çıxış:
Deserializasiyadan sonra kitab siyahısı:
- Çovdarlıqda uçurum kənarında
- Böyük ümidlər
- İlahi komediya
Nümunə 2: Serializasiya HashSet<Integer>
Set<Integer> numbers = new HashSet<>(Arrays.asList(10, 20, 30, 40));
ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("numbers.ser"));
out.writeObject(numbers);
out.close();
ObjectInputStream in = new ObjectInputStream(new FileInputStream("numbers.ser"));
Set<Integer> loadedNumbers = (Set<Integer>) in.readObject();
in.close();
System.out.println("Deserializasiyadan sonra çoxluq: " + loadedNumbers);
Nümunə 3: Serializasiya HashMap<String, Integer>
Map<String, Integer> scores = new HashMap<>();
scores.put("Alice", 100);
scores.put("Bob", 80);
ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("scores.ser"));
out.writeObject(scores);
out.close();
ObjectInputStream in = new ObjectInputStream(new FileInputStream("scores.ser"));
Map<String, Integer> loadedScores = (Map<String, Integer>) in.readObject();
in.close();
System.out.println("Deserializasiyadan sonra Map: " + loadedScores);
Vacib məqamlar
Sıra qorunurmu?
- List üçün (məsələn, ArrayList) elementlərin sırası həmişə saxlanılır.
- Set üçün (HashSet) sıra zəmanətli deyil (serializasiyadan əvvəl də, sonra da).
- Map üçün (HashMap) açar-dəyər cütlərinin sırası zəmanətli deyil (sıra lazımdırsa — LinkedHashMap istifadə edin).
Boş kolleksiyalar problemsiz serializasiya və deserializasiya olunur. Deserializasiyadan sonra boş siyahı/çoxluq/xəritə əldə edəcəksiniz.
Yuvalanmış kolleksiyalar (məsələn, List<List<String>>) bütün daxil olan elementlər serializasiya oluna biləndirsə, düzgün serializasiya olunur.
2. Kolleksiya elementlərinə tələblər
Məhz burada tez-tez ilk ciddi tələ sizi gözləyir!
Kolleksiyadakı bütün elementlər də serializasiya oluna bilən olmalıdır.
Əgər kolleksiyanın heç olmasa bir elementi Serializable interfeysini implement etmirsə, kolleksiyanın serializasiyası NotSerializableException xətası ilə nəticələnəcək. Üstəlik, kolleksiya böyükdürsə və xəta haradasa dərinlikdədirsə, günahkarı axtarmaq maraqlı, amma yorucu bir «kvest»ə çevrilə bilər.
Nümunə: serializasiya olunan kolleksiyada serializasiya olunmayan obyekt
import java.io.*;
import java.util.*;
class NotSerializableClass {
int value;
public NotSerializableClass(int value) {
this.value = value;
}
}
public class NotSerializableDemo {
public static void main(String[] args) throws Exception {
List<Object> list = new ArrayList<>();
list.add("Hello");
list.add(new NotSerializableClass(123)); // <- Hop!
ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("badlist.ser"));
try {
out.writeObject(list); // Burada istisna atılacaq!
} catch (NotSerializableException e) {
System.out.println("Serializasiya xətası: " + e);
}
out.close();
}
}
Nəticə:
Serializasiya xətası: java.io.NotSerializableException: NotSerializableClass
Nə etməli?
Bununla mübarizə sadədir: kolleksiya elementləri ya String və Integer kimi standart tiplər olmalıdır, ya da sizin öz sinifləriniz Serializable interfeysini implement etməlidir. Hər hansı sinif serializasiya oluna bilmirsə, ona implements Serializable əlavə etmək kifayətdir və problem həll olunacaq.
3. Müxtəlif kolleksiyaların serializasiyasının xüsusiyyətləri
Elementlərin sırası qorunurmu?
- List: Bəli, elementlərin sırası saxlanılır.
- Set: Realizasiyadan asılıdır. HashSet-də sıra zəmanətli deyil, LinkedHashSet-də isə saxlanılır.
- Map: HashMap-də sıra zəmanətli deyil, LinkedHashMap-də isə əlavəetmə sırası saxlanılır.
Demonstrasiya:
List<String> list = Arrays.asList("A", "B", "C");
Set<String> set = new HashSet<>(list);
ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("coll.ser"));
out.writeObject(list);
out.writeObject(set);
out.close();
ObjectInputStream in = new ObjectInputStream(new FileInputStream("coll.ser"));
List<String> loadedList = (List<String>) in.readObject();
Set<String> loadedSet = (Set<String>) in.readObject();
in.close();
System.out.println("List: " + loadedList); // həmişə [A, B, C]
System.out.println("Set: " + loadedSet); // [A, C, B] və s. ola bilər
Boş kolleksiyaların serializasiyası
Boş kolleksiyalar problemsiz serializasiya olunur. Deserializasiyadan sonra müvafiq tipdə boş obyekt alacaqsınız.
Yuvalanmış kolleksiyaların serializasiyası
Başqa kolleksiyalar saxlayan kolleksiyaları da serializasiya etmək olar:
List<List<String>> table = new ArrayList<>();
table.add(Arrays.asList("row1-col1", "row1-col2"));
table.add(Arrays.asList("row2-col1", "row2-col2"));
// Serializasiya
ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("table.ser"));
out.writeObject(table);
out.close();
// Deserializasiya
ObjectInputStream in = new ObjectInputStream(new FileInputStream("table.ser"));
List<List<String>> loadedTable = (List<List<String>>) in.readObject();
in.close();
System.out.println(loadedTable);
4. Praktik nümunə: öz sinfinizin obyektlərindən ibarət kolleksiyanın serializasiyası
Gəlin birlikdə «virtual kitabxana» üçün kiçik bir tətbiq yazaq və orada kitabların siyahısını serializasiya edək. Book sinfi serializasiya oluna bilən olmalıdır!
import java.io.*;
import java.util.*;
class Book implements Serializable {
private static final long serialVersionUID = 1L; // sinif versiya uyğunluğu üçün
String title;
String author;
int year;
public Book(String title, String author, int year) {
this.title = title;
this.author = author;
this.year = year;
}
@Override
public String toString() {
return title + " (" + author + ", " + year + ")";
}
}
public class LibraryApp {
public static void main(String[] args) throws Exception {
List<Book> books = new ArrayList<>();
books.add(new Book("Çovdarlıqda uçurum kənarında", "J. D. Selincer", 1951));
books.add(new Book("Böyük ümidlər", "Çarlz Dikkens", 1861));
books.add(new Book("İlahi komediya", "Dante Aligyeri", 1320));
// Siyahını fayla yazırıq
ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("mylibrary.ser"));
out.writeObject(books);
out.close();
// Siyahını geri oxuyuruq
ObjectInputStream in = new ObjectInputStream(new FileInputStream("mylibrary.ser"));
List<Book> loadedBooks = (List<Book>) in.readObject();
in.close();
System.out.println("Fayldakı kitablar:");
for (Book b : loadedBooks) {
System.out.println("- " + b);
}
}
}
5. Kolleksiyaların serializasiyasında tipik səhvlər
Səhv №1: Kolleksiya elementində NotSerializableException. Əgər kolleksiyanın heç olmasa bir elementi serializasiya olunmursa, serializasiya NotSerializableException xətası ilə «yıxılacaq». Məsələn, təsadüfən kolleksiyaya Serializable-ı implement etməyən obyekt əlavə etmisinizsə və ya öz sinfinizə bu interfeysi əlavə etməyi unutmusanızsa.
Səhv №2: Serializasiya və deserializasiya arasında sinifin dəyişdirilməsi. Əgər obyektlərdən ibarət kolleksiyanı serializasiya etmisinizsə və sonra sinifin strukturunu dəyişmisinizsə (məsələn, sahələr əlavə etmisiniz və ya silmisiniz), deserializasiya zamanı InvalidClassException baş verə bilər. Bunun qarşısını almaq üçün sinifdə serialVersionUID sahəsindən istifadə edin.
Səhv №3: transient və ya static sahələri olan kolleksiyanın serializasiyası. transient və ya static kimi işarələnmiş sahələr serializasiya olunmur. Əgər obyektləriniz bu cür sahələrdən asılıdırsa, deserializasiyadan sonra onlar ilkin (məsələn, null və ya 0) dəyərlərə sahib olacaqlar.
Səhv №4: Yuvalanmış, lakin serializasiya olunmayan obyektləri olan kolleksiyaların serializasiyası. Əgər kolleksiyada Serializable-ı implement etməyən yuvalanmış kolleksiyalar və ya obyektlər varsa, xəta ən dərin səviyyədə baş verəcək — problemi harada axtarmaq lazım olduğunu dərhal anlamaq həmişə asan olmur. Bütün yuvalanma səviyyələrini yoxlayın!
Səhv №5: Böyük kolleksiyalarda məhsuldarlıq. Kolleksiya çox böyükdürsə, serializasiya çox vaxt və disk yeri tuta bilər. Belə hallarda axın (stream) serializasiyasını və ya kolleksiyanı hissələrə bölməyi düşünmək olar.
GO TO FULL VERSION