Explicación simple de Java sobre serialización y deserialización y ejemplos de implementación de código


flujo de serialización

1. Introducción

Para lograr el almacenamiento a largo plazo de datos almacenados a corto plazo, el flujo correspondiente a este proceso es el flujo de serialización.

El almacenamiento de datos se divide en dos categorías.

  1. Almacenamiento a corto plazo : almacenado en la memoria y liberado cuando se cierra el programa. Tales como: objetos, colecciones, variables, matrices, etc.
  2. Almacenamiento a largo plazo : almacenados en disco, los datos aún existen incluso si se cierra el programa. Tales como: archivo

Serialización : colocar datos de la memoria en el disco puede lograr un almacenamiento de datos a largo plazo.

Deserialización : poner datos del disco en la memoria.

2. Precauciones

ObjectInputStream y ObjectOutputStream se utilizan principalmente para la serialización y deserialización de objetos.

La serialización y deserialización son métodos comunes para el almacenamiento persistente de objetos.

Todos los objetos serializados en clases locales deben implementar la interfaz java.io.Serilizable.

Qué puede lograr una clase que implementa la interfaz Serilizable:

  1. Se puede serializar
  2. Todos los elementos de la clase que se serializan deben admitir la serialización.
  3. Todos los subtipos de una clase serializable son ellos mismos serializables.
  4. La interfaz en sí no tiene métodos ni campos, solo se usa para representar semántica serializable.

Si necesita serializar varios archivos en el local, intente no serializarlos en un solo archivo. Si necesita serializar varios archivos en el local, el método habitual es guardar una colección . Almacene varios objetos en una colección y luego serialice la colección localmente.

3. Preguntas frecuentes

  1. ClassNotFoundException: no se encontró la clase actual
    . Motivo: la deserialización depende de archivos de código de bytes cuando se ejecuta. Cuando la clase no tiene clase, el archivo de código de bytes no se puede crear y la deserialización falla.
  2. java.io.InvalidClassException: clase no válida
    Motivo: el serialVersionUID del sistema no está declarado y la clase se cambia durante la deserialización. El sistema piensa que la clase actual ya no es la clase original y considera que esta clase no es válida
  3. ¿Cuál es la diferencia entre usar el serialVersionUID del sistema y un UID personalizado?
    Cuando se utiliza el UID del sistema: el ID no se puede configurar manualmente, lo genera el compilador de forma predeterminada. Una vez que se cambia la clase, la identificación se reasignará;
    cuando se usa un UID personalizado: la identificación no cambiará durante la serialización y deserialización. Entonces, al deserializar, incluso si se realizan algunos cambios en la clase, la deserialización puede continuar.

Código de muestra

    package com.cq.test;
    
    import java.io.*;
    import java.util.ArrayList;
    import java.util.List;
    
    /**
     * @author: Mercury
     * Date: 2022/4/6
     * Time: 9:02
     * Description:序列化流
     * Version:1.0
     */
    public class SerializableTest {
    
    
        public static void main(String[] args) {
    
    
            test1();
            test2();
        }
        //序列化
        public static void test1(){
    
    
            try (ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream("F:\\bigDataWorkSpace\\part01\\day21_0406\\person.txt"));){
    
    
                //对对象进行序列化
                List<Person> list = new ArrayList<>();
                list.add(new Person("张三",20,177));
                list.add(new Person("wangwu",21,177));
                //可序列化类的所有子类本身都是可序列化的
                list.add(new Child("lisi",20,155,100));
                //将多个对象序列化的时候,需要先放入一个集合中,然后再序列化
                objectOutputStream.writeObject(list);
            } catch (IOException e) {
    
    
                e.printStackTrace();
            }
        }
        //逆序列化
        public static void test2(){
    
    
            try(ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream("F:\\bigDataWorkSpace\\part01\\day21_0406\\person.txt"));) {
    
    
                //反序列化
                //反序列多个对象的时候,同样需要一个集合来保存反序列化的多个对象
                List list = (ArrayList)objectInputStream.readObject();//需要强制转换ArrayList
                System.out.println(list);
            } catch (IOException e) {
    
    
                e.printStackTrace();
            } catch (ClassNotFoundException e) {
    
    
                e.printStackTrace();
            }
        }
    }
    //Person类的对象可以实现序列化,必须让其实现Serializable接口
    class Person implements Serializable{
    
    
        // UID由用户进行指定,默认值为1L
        public static final long serialVersionUID = -24323423423423221L;
        private String name;
        private int age;
        private double height;
    
        public void show(){
    
    
            System.out.println("show--Person");
        }
    
        @Override
        public String toString() {
    
    
            return "Person{" +
                    "name='" + name + '\'' +
                    ", age=" + age +
                    ", height=" + height +
                    '}';
        }
    
        public Person() {
    
    
        }
    
        public Person(String name, int age, double height) {
    
    
            this.name = name;
            this.age = age;
            this.height = height;
        }
    
        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 double getHeight() {
    
    
            return height;
        }
    
        public void setHeight(double height) {
    
    
            this.height = height;
        }
    }
    
    //可序列化类的所有子类本身都是可序列化
    class Child extends Person{
    
    
        private double weight;
    
        public Child() {
    
    
        }
    
        public Child(double weight) {
    
    
            this.weight = weight;
        }
    
        public Child(String name, int age, double height, double weight) {
    
    
            super(name, age, height);
            this.weight = weight;
        }
    
        public double getWeight() {
    
    
            return weight;
        }
    
        public void setWeight(double weight) {
    
    
            this.weight = weight;
        }
    
        @Override
        public String toString() {
    
    
            return "Child{" +
                    "weight=" + weight +
                    '}';
        }
    }

Nota :

  • Si desea que un objeto sea serializable, la clase debe implementar la interfaz Serializable .
  • Una clase que no implementa la interfaz Serializable no puede serializar ni deserializar ninguno de sus estados.
  • No solo se requiere que la clase actual sea serializable, sino que todos los elementos de la clase actual deben ser serializables.
  • Al serializar varios objetos, primero debe colocarlos en una colección y luego serializarlos; lo mismo ocurre con la deserialización, pero se requiere conversión de tipos.

Resumir

  • Utilice flujos de serialización y flujos de deserialización de manera adecuada, y utilícelos junto con flujos de entrada y flujos de salida.
  • La clase a serializar debe implementar la interfaz Serializable, siempre que la interfaz esté implementada, se puede serializar, incluidas colecciones, clases de empaquetado, etc.
  • La clase que se serializa debe garantizar que tanto la clase actual como las clases internas implementen la interfaz serializable.

Supongo que te gusta

Origin blog.csdn.net/qq_45263520/article/details/123984008
Recomendado
Clasificación