Problems encountered when using the Serializable interface in actual development

The class implements the serialization interface, but there are members that do not implement the serialization interface. When running, an error is reported: java.io.NotSerializableException.

You need to use the transient keyword to modify members that do not implement the serialization interface.
It is worth noting that if the value of a member variable that does not implement the serialization interface is null, no error will be reported even if the transient keyword is not added.

Why can't static variables be serialized?

Static variables do not participate in serialization. What is serialized is the member fields of the object.

Multiple reference writing problem: the same reference writes different object contents multiple times, but the object taken out is exactly the same. Demo code:

// 序列化
FileOutputStream fos = new FileOutputStream(filePath);
ObjectOutputStream oos = new ObjectOutputStream(fos);
Person2 personWrite = new Person2("wzc", 32);
oos.writeObject(personWrite);
personWrite.setAge(33);
oos.writeObject(personWrite);
oos.close();
// 反序列化
FileInputStream fis = new FileInputStream(filePath);
ObjectInputStream ois = new ObjectInputStream(fis);
Person2 personRead1 = (Person2) ois.readObject();
Person2 personRead2 = (Person2) ois.readObject();
ois.close();
System.out.println("personWrite:" + personWrite);
System.out.println("personRead1:" + personRead1);
System.out.println("personRead2:" + personRead2);
System.out.println("personRead1 == personRead2:" + (personRead1 == personRead2));
打印信息:

personWrite:Person2@692404036{
    
    name='wzc', age=33}
personRead1:Person2@1072408673{
    
    name='wzc', age=32}
personRead2:Person2@1072408673{
    
    name='wzc', age=32}
personRead1 == personRead2:true

The object content written for the first time using personWrite is "wzc", 32; the
object content written for the second time using personWrite is "wzc", 33;
however, the deserialization reads exactly the same object.

Solution:

  • Add code oos.reset(); before the second write.
  • Replace the code written for the second time: oos.writeObject(personWrite); with oos.writeUnshared(personWrite);
  • Try to avoid writing with multiple references and use different references.

The parent class implements Serializable, but the subclass does not. Can the subclass be serialized?

Can.

The subclass implements serialization, but the parent class does not. How to serialize the data of the parent class?

First, add a null parameter constructor to the parent class, otherwise an error will be reported: java.io.InvalidClassException: com.java.advanced.features.io.serialize.serializable.Man; no valid constructor;
secondly, let the subclass be responsible for serialization (Deserialization) The domain of the parent class.
code show as below:

public class Person7 {
    
    
    public String name;
    public int age;
    // 添加了无参构造器
    public Person7() {
    
    
    }
    public Person7(String name, int age) {
    
    
        this.name = name;
        this.age = age;
    }
}
public class Man3 extends Person7 implements Serializable  {
    
    
    public double salary;

    public Man3(String name, int age, double salary) {
    
    
        super(name, age);
        this.salary = salary;
    }

    private void writeObject(ObjectOutputStream oos) throws IOException {
    
    
        // 先序列化本类对象
        oos.defaultWriteObject();
        // 再序列化父类的域
        oos.writeObject(name);
        oos.writeInt(age);
    }

    private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
    
    
        // 先反序列化本类对象
        ois.defaultReadObject();;
        // 再反序列化父类的域
        name = (String) ois.readObject();
        age = ois.readInt();
    }
}

If there is one more field during serialization and one less field during deserialization, or if there is one less field during serialization and one more field during deserialization, will an error be reported?

The value of serialVersionUID needs to be explicitly declared, such as 1L.

private static final long serialVersionUID = 1L;
Because calculating the default serialVersionUID is highly sensitive to the details of the class, it may vary widely depending on the compiler implementation, which may cause unexpected InvalidClassException during the deserialization process.

If the serialVersionUID of the class is consistent, even if the class during serialization and the class at deserialization are somewhat different, the object will still be deserialized as much as possible.

The execution order of writeReplace, writeObject, readResolve, and readObject
is writeReplace before writeObject, and readResolve after readObject.

Deserialization breaks singleton, how to solve it?

Add the readResovle() method to the singleton:

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

    private SingletonSerializeFix() {
    
    
        //no instance
    }

    public static SingletonSerializeFix getInstance() {
    
    
        return SingletonHolder.instance;
    }

    private static class SingletonHolder {
    
    
        private static SingletonSerializeFix instance = new SingletonSerializeFix();
    }

    private Object readResolve() {
    
    
        return SingletonHolder.instance;
    }
}

Guess you like

Origin blog.csdn.net/lzfaq/article/details/125672376