Язык программирования Java поддерживает механизм, который может представить объект в виде последовательности байтов. Эта последовательность содержит информацию как сам объект, так и информацию о типе объекта и типах данных, которые хранятся в этом объекте.
Такой механизм называется сериализация.
После того как сериализованный объект записан в виде файла, он может быть прочитан из файла и десериализован, то есть, восстановлен из памяти.
Наиболее важным моментом является то, что этот процесс не зависит от JVM, т.е. объект может быть сериализован на одной платформе, а десериализован (полностью воспроизведён) на абсолютно другой.
Такие классы, как ObjectInputStream и ObjectOutputStream, являются потоками, которые содержат методы для сериализации и десериализации объектов.
Для того чтобы класс мог быть сериализован, должны быть соблюдены определённые условия:
- Класс должен имплементировать интерфейс java.io.Serializable
- Все поля класса должны быть сериализованы. Поля, которые мы хотим исключить, должны быть отмечены, как transient.
Для понимания того, как это работает на практике, рассмотрим пример простого приложения, в котором мы попробуем сериализовать, а затем – десериализовать класс Developer, который содержит информацию о разработчике.
Пример:
Класс Developer
import java.io.Serializable;
public class Developer implements Serializable {
private String name;
private String specialty;
private int experience;
transient private int salary;
public Developer(String name, String specialty, int experience, int salary) {
this.name = name;
this.specialty = specialty;
this.experience = experience;
this.salary = salary;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSpecialty() {
return specialty;
}
public void setSpecialty(String specialty) {
this.specialty = specialty;
}
public int getExperience() {
return experience;
}
public void setExperience(int experience) {
this.experience = experience;
}
public int getSalary() {
return salary;
}
public void setSalary(int salary) {
this.salary = salary;
}
public void doJob() {
System.out.println(this.specialty + " developer " + this.name + " is writing code...");
}
@Override
public String toString() {
return "Developer:" +
"\nName: " + name +
"\nSpecialty: " + specialty +
"\nExperience: " + experience +
"\nSalary: " + salary + "\n";
}
}
Класс SerializationDemo
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
public class SerializationDemo {
public static void main(String[] args) throws IOException {
Developer developer = new Developer("Proselyte", "Java", 3, 2000);
FileOutputStream fileOutputStream =
new FileOutputStream("resources/Developer.info");
ObjectOutputStream outputStream =
new ObjectOutputStream(fileOutputStream);
outputStream.writeObject(developer);
outputStream.close();
fileOutputStream.close();
System.out.println("Developer serialized successfully.");
}
}
В результате работы программы, которая сериализирует объект, мы получим, примерно следующий результат:
/*Some System Messages*/
Developer serialized successfully.
Класс DeserializationDemo
import java.io.FileInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
public class DeserializationDemo {
public static void main(String[] args) throws IOException, ClassNotFoundException {
Developer developer = null;
FileInputStream fileInputStream =
new FileInputStream("resources/Developer.info");
ObjectInputStream inputStream = new ObjectInputStream(fileInputStream);
developer = (Developer) inputStream.readObject();
inputStream.close();
fileInputStream.close();
System.out.println("Deserializing... Developer:");
System.out.println(developer);
}
}
В результате работы программы, которая десериализирует объект, мы получим, примерно следующий результат:
/*Some System Messages*/
Deserializing... Developer:
Developer:
Name: Proselyte
Specialty: Java
Experience: 3
Salary: 0
Как мы видим, все поля класса, кроме salary (зарплаты) были сериализованы и десериализованы. Поле salary получило значение по умолчанию для своего типа данных (для типа данных int это 0).
В этом уроке мы изучили основы сериализации и рассмотрели примеры приложений, которые сериализуют и восстанавливают объект.
В следующем уроке мы начнём изучать многопоточность.