ПУТЕШЕСТВИЕ ПО РАЗРАБОТКЕ ПРОГРАММНОГО ОБЕСПЕЧЕНИЯ

5 вещей, которые вы должны знать о сериализации и десериализации в Java

Инженер-программист по сериализации и десериализации Java должен знать

Обзор

Сериализация в Java помогает преобразовать существующий объект в поток байтов. И наоборот, десериализация делает поток байтов сериализации объектом. Используя сериализацию и десериализацию в Java, информацию об объектах можно переносить с одной JVM на другую. Давайте перейдем к деталям статьи, чтобы понять, как работают сериализация и десериализация.

#1 Сериализация

Прежде чем приступить к подробному описанию статьи, я хотел бы предоставить классы SerializeUtils.java и Person.java, которые помогут нам обрабатывать сериализацию и десериализацию для всех примеров в этой статье.

SerializeUtils.java

package com.techteam.serialization;

import java.io.*;

public class SerializeUtils {
    public static <T> void serialize(T input, String fileName) throws IOException {
        FileOutputStream file = new FileOutputStream(fileName);
        ObjectOutputStream out = new ObjectOutputStream(file);
        out.writeObject(input);
        out.close();
        file.close();
    }

    public static <T> T deserialize(String fileName) throws IOException, ClassNotFoundException {
        FileInputStream file = new FileInputStream(fileName);
        ObjectInputStream in = new ObjectInputStream(file);
        T result = (T) in.readObject();

        return result;
    }

    public static void externalSeialize(Externalizable e, String fileName) throws IOException {
        FileOutputStream file = new FileOutputStream(fileName);
        ObjectOutputStream out = new ObjectOutputStream(file);
        e.writeExternal(out);
        out.close();
        file.close();
    }

    public static void externalDeseialize(Externalizable e, String fileName) throws IOException, ClassNotFoundException {
        FileInputStream file = new FileInputStream (fileName);
        ObjectInputStream in = new ObjectInputStream (file);
        e.readExternal(in);
        in.close();
        file.close();
    }
}

Person.java

package com.techteam.serialization;

import java.io.Serializable;

public class Person implements Serializable {
    private static final long serialVersionUID = 1L;

    private int id;
    private String name;
    private int age;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
}

Как упоминалось в обзоре, сериализация для изменения объектов стала потоком байтов. Это означает, что вся информация об объекте преобразуется в поток байтов, такой как метод, свойства и данные. Давайте перейдем к примеру, чтобы увидеть, как мы сериализуем объект:

package com.techteam.serialization;

import java.io.IOException;

public class SerializationMain {

    public static void main(String[] args) throws IOException {
        Person p = new Person();
        p.setId(1);
        p.setName("Tech team members");
        p.setAge(20);

        SerializeUtils.serialize(p, "/person.txt");
    }
}

После процесса сериализации у нас есть файл с таким содержимым:

#2 Десериализация

В части сериализации мы создали поток байтов путем сериализации объекта. Мгновенно, с тем, что дано потоковыми данными, давайте посмотрим, как мы вернемся к объекту с десериализацией в нашем примере ниже:

package com.techteam.serialization;

import java.io.IOException;

public class DeserializationMain {
    public static void main(String[] args) throws IOException, ClassNotFoundException {
        Person p = SerializeUtils.deserialize("/person.txt");

        System.out.println("Person data:");
        System.out.println(p.getId());
        System.out.println(p.getName());
        System.out.println(p.getAge());
    }
}

Вот данные после процесса десериализации:

#3 UID серийной версии

serialVersionUID означает уникальный идентификационный номер для каждой версии процесса сериализации и десериализации. Этот номер используется, чтобы убедиться, что как сериализованные, так и десериализованные объекты используют совместимые классы. Для Person.java я хотел бы увеличить serialVersionUID до 2, теперь давайте посмотрим на вывод, когда мы десериализуем файл person.txt.

# 4 Временное ключевое слово

Для процесса сериализации и десериализации иногда нам не нужно сериализовать всю информацию об объекте. Используя переходный процесс для переменных, он будет игнорировать эти переменные из сериализуемого объекта. Пример ниже поможет вам более четко об этом:

package com.techteam.serialization;

import java.io.IOException;
import java.io.Serializable;

public class PersonWithTransient implements Serializable {

    private static final long serialVersionUID = 1L;

    private int id;
    private String name;
    private transient int age;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public static void main(String[] args) throws IOException, ClassNotFoundException {
        PersonWithTransient p = new PersonWithTransient();
        p.setId(2);
        p.setName("Tech team members(transient)");
        p.setAge(50);

        SerializeUtils.serialize(p, "/person_transient.txt");

        PersonWithTransient deserializeP = SerializeUtils.deserialize("/person_transient.txt");
        System.out.println("Person without transient data:");
        System.out.println(deserializeP.getId());
        System.out.println(deserializeP.getName());
        System.out.println(deserializeP.getAge());
    }
}

В приведенном выше коде мы использовали временный ключ для переменной age, теперь давайте посмотрим на наш вывод после процесса сериализации и десериализации.

# 5 Внешний интерфейс

В Java, когда мы хотим настроить процесс сериализации и десериализации, мы можем использовать переходный процесс, чтобы игнорировать переменные, которые нам не нужны для процесса сериализации и десериализации. Другой способ упростить и повысить производительность — использовать интерфейс Externalizable вместо непосредственного использования интерфейса Serializable. Чтобы продемонстрировать это, давайте посмотрим на пример ниже:

package com.techteam.serialization;

import java.io.Externalizable;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectOutput;

public class PersonExternalizable implements Externalizable {
    private static final long serialVersionUID = 1L;
    private int id;
    private String name;
    private int age;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public void writeExternal(ObjectOutput out) throws IOException {
        out.writeUTF(this.name);
        out.writeInt(this.age);
    }

    @Override
    public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
        this.name = in.readUTF();
        this.age = in.readInt();
    }

    public static void main(String[] args) throws IOException, ClassNotFoundException {
        PersonExternalizable p = new PersonExternalizable();
        p.setId(3);
        p.setName("Tech team members(Externalizable)");
        p.setAge(30);

        SerializeUtils.externalSeialize(p, "/person_externalizable.txt");

        PersonExternalizable deserializeP = new PersonExternalizable();
        SerializeUtils.externalDeseialize(deserializeP, "/person_externalizable.txt");
        System.out.println("Person data:");
        System.out.println(deserializeP.getId());
        System.out.println(deserializeP.getName());
        System.out.println(deserializeP.getAge());
    }
}

Как вы можете видеть, используя Externalizable, мы можем легко написать пользовательскую логику, игнорировать переменные и получить более высокую производительность, чем при непосредственном использовании Serializable. Теперь давайте посмотрим на вывод наших процессов с кодом выше:

Заключение

Я думаю, что в этой статье вы сможете получить представление о том, как сериализация и десериализация работают в Java. С приведенными выше примерами это также может помочь вам в практическом опыте. Это все, чем я хочу поделиться с вами о сериализации и десериализации. Надеюсь, контент будет полезен для вас. Спасибо!