Java serialization and deserialization

Serialization and deserialization: Reference link
SerialversionUID details: Reference link
Differences between bytes and characters: Reference link

In the past, serialization was implemented by some methods. Later, the business requirements need to be deeply copied before research. Read other people's blogs and draw some conclusions.

  1. Serialization is the process of converting Java objects into byte sequences (byte streams). Then, deep copy is realized through streaming operation, and the serialized data is convenient for storage and transmission. Deserialization is to deserialize the byte sequence into Java objects

Convenient storage: because the object will be recycled, it can be continuously stored on disk after serialization
Convenient transmission: byte sequence (binary form) can be transmitted and propagated on the network.

  1. It is best to set a SerialversionUID, because serialization and deserialization are performed by comparing the SerialversionUID. Although one will be generated by default without setting the interface, you should know that the process of serializing objects is generally object - > serialization - > storage or transmission - > deserialization.
    for instance:
    First create an entity class Student
import lombok.Data;

import java.io.Serializable;

@Data
public class Student implements Serializable {
    private Integer id;
    private String name;
    private String sex;
}

Then create a test class SerializableTest

import serialization.entity.Student;

import java.io.*;

public class SerializableTest {
    public static void main(String[] args) throws Exception {
        serializeStudent();
        Student student = deserializeStudent();
        System.out.println("name:" + student.getName());
        System.out.println("sex:" + student.getSex());
    }

    private static void serializeStudent() throws IOException {
        Student student = new Student();
        student.setId(1);
        student.setName("Zhang San");
        student.setSex("male");

        ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(
                new File("F:/student.txt")));
        out.writeObject(student);
        System.out.println("Serialization succeeded");
        out.close();
    }

    private static Student deserializeStudent() throws Exception {
        ObjectInputStream in = new ObjectInputStream(new FileInputStream(new File("F:/student.txt")));
        Student student = (Student) in.readObject();
        System.out.println("Deserialization succeeded");
        return student;
    }
}

Execution results:

Serialization succeeded
 Deserialization succeeded
name:Zhang San
sex:male

It is possible to succeed without specifying SerialversionUID at this time, but object - > serialization - > storage or transmission - > deserialization. Shall we modify the Student class before deserialization?

At this time, let's modify the code, comment out the deserialization code and serialize it first.

import serialization.entity.Student;

import java.io.*;

public class SerializableTest {
    public static void main(String[] args) throws Exception {
        serializeStudent();
//        Student student = deserializeStudent();
//        System.out.println("name:" + student.getName());
//        System.out.println("sex:" + student.getSex());
    }

    private static void serializeStudent() throws IOException {
        Student student = new Student();
        student.setId(1);
        student.setName("Zhang San");
        student.setSex("male");

        ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(
                new File("F:/student.txt")));
        out.writeObject(student);
        System.out.println("Serialization succeeded");
        out.close();
    }

//    private static Student deserializeStudent() throws Exception {
//        ObjectInputStream in = new ObjectInputStream(new FileInputStream(new File("F:/student.txt")));
//        Student student = (Student) in.readObject();
//        System.out.println("deserialization succeeded");
//        return student;
//    }
}

Operation results:

Serialization succeeded

Modify Student class

import lombok.Data;

import java.io.Serializable;

@Data
public class Student implements Serializable {
    private Integer id;
    private String name;
    private String sex;
    private String address;
}

Comment out the serialization method and deserialize it

import serialization.entity.Student;

import java.io.*;

public class SerializableTest {
    public static void main(String[] args) throws Exception {
//        serializeStudent();
        Student student = deserializeStudent();
        System.out.println("name:" + student.getName());
        System.out.println("sex:" + student.getSex());
    }

//    private static void serializeStudent() throws IOException {
//        Student student = new Student();
//        student.setId(1);
//        student.setName("Zhang San");
//        student.setSex("male");
//
//        ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(
//                new File("F:/student.txt")));
//        out.writeObject(student);
//        System.out.println("serialization succeeded");
//        out.close();
//    }

    private static Student deserializeStudent() throws Exception {
        ObjectInputStream in = new ObjectInputStream(new FileInputStream(new File("F:/student.txt")));
        Student student = (Student) in.readObject();
        System.out.println("Deserialization succeeded");
        return student;
    }
}

Execution results:

Exception in thread "main" java.io.InvalidClassException: serialization.entity.Student; local class incompatible: stream classdesc serialVersionUID = 3846952599709361171, local class serialVersionUID = -4606152942663467236
	at java.io.ObjectStreamClass.initNonProxy(ObjectStreamClass.java:699)
	at java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1885)
	at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1751)
	at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:2042)
	at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1573)
	at java.io.ObjectInputStream.readObject(ObjectInputStream.java:431)
	at serialization.demo.SerializableTest.deserializeStudent(SerializableTest.java:30)
	at serialization.demo.SerializableTest.main(SerializableTest.java:10)

Process finished with exit code 1

It can be seen that the serialversionuids of the two executions do not match, resulting in the generation of Java io. Invalidclassexception exception exception, so as long as SerialversionUID is specified

//Specifies the correct writing of serialVersionUID
private static final long serialVersionUID = 3846952599709361171L;

//If the SerialversionUID is not known after serialization, it can be obtained through reflection
Object obj = Student.class.newInstance();
Field field = Student.class.getDeclaredField("serialVersionUID");
field.setAccessible(true);
System.out.println(field.getLong(obj));
  1. The last thing you need to know is the difference between byte stream and character stream.
    Byte stream: in the transmission process, the most basic unit of transmitted data is the byte stream.
    Character stream: in the transmission process, the most basic unit of transmitted data is the character stream.

This may be A little confusing. Bytes are actually the eight basic types of Byte (bit) units of Java, and the characters are usually 'A', 'B', '$', '&', etc. the Byte size depends on your encoding (environment), as follows:

  • In ASCII code, an English letter (regardless of case) is one byte and a Chinese character is two bytes.
  • In UTF-8 coding, an English word is one byte and a Chinese word is three bytes.
  • In Unicode coding, one English is one byte and one Chinese is two bytes.
  • Symbol: English punctuation is one byte and Chinese punctuation is two bytes. For example: English full stop Take up 1 byte, Chinese period. Occupies a size of 2 bytes.
  • In UTF-16 coding, 2 bytes are required for the storage of an English alphabetic character or a Chinese character (4 bytes are required for the storage of some Chinese characters in Unicode extension).
  • In UTF-32 encoding, 4 bytes are required for the storage of any character in the world.

Keywords: Java Back-end

Added by exhaler on Tue, 04 Jan 2022 12:41:01 +0200