Premise: CopyOnWriteArrayList can be serialized, and its internal elements will also be serialized. Therefore, it triggered the consideration of TRANSIENT: “Whether transient keyword modifies variables can be serialized”

Transient keyword

1. The first impression of transient keyword: the variable modified by it cannot be serialized (as verified by the following example)

Entity

public class TestStream implements Serializable {

  private String id;
  private transient String name;
  private transient volatile Object[] array;
  private transient Integer age;

  public String getId() {
    return id;
  }

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

  public String getName() {
    return name;
  }

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

  public Object[] getArray() {
    return array;
  }

  public void setArray(Object[] array) {
    this.array = array;
  }

  @Override
  public String toString() {
    return "TestStream{" +
        "id='" + id + '\'' + "age='" + age + '\'' + ", name='" + name + '\' ' +
        ", array=" + Arrays.toString(array) +
        '} ';
  }

  public  Integer getAge() {
    return age;
  }

  public  void setAge(Integer age) { this.age = age; }}Copy the code

TestClass

  @Test
  public void testSeri() throws Exception {// Tests serializing TestStreamtestStream = new TestStream();
    testStream.setId("123");
    testStream.setName("QBH");
    testStream. SetArray (new Object [] {1, 2, 3});testStream.setAge(18);
    System.out.println(testStream); ByteArrayOutputStream bo = new ByteArrayOutputStream(); ObjectOutputStream oo = new ObjectOutputStream(bo); oo.writeObject(testStream); ByteArrayInputStream bi = new ByteArrayInputStream(bo.tobyteArray ()); ObjectInputStream oi = new ObjectInputStream(bi); TestStream object1 = (TestStream)oi.readObject(); System.out.println(object1); }Copy the code

Result

TestStream{id= age name array is a transient variable that is not serialized'007'age='18', name='juejin', array=[1, 2, 3]}
TestStream{id='007'age='null', name='null', array=null}
Copy the code

WriteObject and readOject

WirteObject method

This method is called when the object “overrides” it for serialization (reflection is used to check for overrides). Knowing when a method is called, you know what it’s for: custom serialization steps

private void writeObject(java.io.ObjectOutputStream s)
      throws java.io.IOException{}
Copy the code

This method is called when the object “overrides” the deserialization (reflection is used to check for overrides) purpose: Customize the deserialization step

private void readObject(java.io.ObjectInputStream s)
      throws java.io.IOException, ClassNotFoundException{}
Copy the code

example

Entity: rewrite the writeObject and readObject methods (CopyOnwriteArrayList also rewritten, cpoy to come over for some of the properties of custom sequence | deserialization)

package entity; import java.io.Serializable; import java.util.Arrays; import sun.misc.SharedSecrets; public class TestStream implements Serializable { private String id; private transient String name; private transient volatile Object[] array; // Consistent with CopyOnWriteArrayList array private TRANSIENT Integer AGE; public StringgetId() {
    return id;
  }

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

  public String getName() {
    return name;
  }

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

  public Object[] getArray() {
    return array;
  }

  public void setArray(Object[] array) {
    this.array = array;
  }

  @Override
  public String toString() {
    return "TestStream{" +
        "id='" + id + '\'' + "age='" + age + '\'' + ", name='" + name + '\' ' +
        ", array=" + Arrays.toString(array) +
        '} ';
  }

  public  Integer getAge() {
    return age;
  }

  public  void setAge(Integer age) { this.age = age; } private void writeObject(java.io.ObjectOutputStream s) throws java.io.IOException { s.defaultWriteObject(); Object[] elements = getArray(); // Write out array length s.writeInt(elements.length); // Serialize the length of the array. // Serialize age attributes // Write out all elementsin the proper order.
    for (Object element : elements)
      s.writeObject(element);

  }
  private void readObject(java.io.ObjectInputStream s) throws java.io.IOException, ClassNotFoundException { s.defaultReadObject(); int len = s.readInt(); // Read the length of arraysetAge(s.readInt()); / / read the value of the age SharedSecrets. GetJavaOISAccess () checkArray (s, Object [] class, len); Object[] elements = new Object[len]; // Readin all elements in the proper order.
    for (int i = 0; i < len; i++)
      elements[i] = s.readObject();
    setArray(elements); }}Copy the code

TestClass

  @Test
  public void testSeri() throws Exception {// Tests serializing TestStreamtestStream = new TestStream();
    testStream.setId("123");
    testStream.setName("QBH");
    testStream. SetArray (new Object [] {1, 2, 3});testStream.setAge(18);
    System.out.println(testStream); ByteArrayOutputStream bo = new ByteArrayOutputStream(); ObjectOutputStream oo = new ObjectOutputStream(bo); oo.writeObject(testStream); ByteArrayInputStream bi = new ByteArrayInputStream(bo.tobyteArray ()); ObjectInputStream oi = new ObjectInputStream(bi); TestStream object1 = (TestStream)oi.readObject(); System.out.println(object1); }Copy the code

Result

TestStream{id='007'age='18', name='juejin', array=[1, 2, 3]}
TestStream{id='007'age='18', name='null', array=[1, 2, 3]}
Copy the code

conclusion

So it is not true that transient attributes cannot be serialized. However, the write and read attributes must correspond to each other in order to avoid serialization errors

thinking

Why does CopyOnWriteArrayList make array transient and then serialize writeObject and readObject?

: Because the array of CopyOnWriteArrayList is a “tuple”, the size of the array is usually not equal to the actual number of elements, so to avoid the problem of the number of elements in the array when deserialization (write a simple version of the List to test), so rewrite the serialization step.

This article deals with serialization knowledge is very shallow, only introduces how to customize serialization, if you want to learn more about serialization, can debug source tracing