preface
Java serialization is certainly no stranger to you. When using some open source frameworks, such as dubbo, You must have stepped on the case where the entity class does not implement the serialization interface (java.io.Serializable) and reported an error. Have you ever thought about why you should serialize the entity class? What should you do if the entity class references a class that cannot be serialized? Let's talk about the Java serialization I explored and its use scenarios.
How to serialize
- First, the entity class should implement the Serializable interface
public class Student implements java.io.Serializable { private String name; private int age; // getter setter ... }
- You can then serialize to a local file using ObjectOutStream
// Create output stream ObjectOutStream out = new ObjectOutputStream(new FileOutputStream("student.dat")) // Create an object that needs to be serialized Student jack = new Student("Jack", 21); Student jim = new Student("Jim", 20); // Write stream out.writeObject(jack); out.writeObject(jim);
How to deserialize
// Read back object data ObjectInputStream in = new ObjectInputStream(new FileInputStream("student.dat")); // Then use the readObject method to get them in the order in which they are written Student jack = (Student) in.readObject(); Student jim = (Student) in.readObject();
Method call order
Note: the serialization write order and deserialization read order should be consistent
For example:
writeInt(a), writeInt(b)
readInt(a), readInt(b)
What should I do to reference properties that cannot be serialized?
It's simple. There are several ways
- The java keyword {transient is used above the attribute
- The method is annotated with @ Transient
- If conditions permit, it can also be changed to static attribute
Because the static data is not in heap memory, but in the static method area
Complete example
Let's take a look at how the source code of our commonly used java ArrayList completes serialization
public class ArrayList<E> extends AbstractList<E> implements List<E>, RandomAccess, Cloneable, java.io.Serializable { private static final long serialVersionUID = 8683452581122892189L; /** * The array buffer into which the elements of the ArrayList are stored. * The capacity of the ArrayList is the length of this array buffer. Any * empty ArrayList with elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA * will be expanded to DEFAULT_CAPACITY when the first element is added. */ transient Object[] elementData; // non-private to simplify nested class access /** * The size of the ArrayList (the number of elements it contains). * * @serial */ private int size; ··· /** * Save the state of the <tt>ArrayList</tt> instance to a stream (that * is, serialize it). * * @serialData The length of the array backing the <tt>ArrayList</tt> * instance is emitted (int), followed by all of its elements * (each an <tt>Object</tt>) in the proper order. */ private void writeObject(java.io.ObjectOutputStream s) throws java.io.IOException{ // Write out element count, and any hidden stuff int expectedModCount = modCount; s.defaultWriteObject(); // Write out size as capacity for behavioural compatibility with clone() s.writeInt(size); // Write out all elements in the proper order. for (int i=0; i<size; i++) { s.writeObject(elementData[i]); } if (modCount != expectedModCount) { throw new ConcurrentModificationException(); } } /** * Reconstitute the <tt>ArrayList</tt> instance from a stream (that is, * deserialize it). */ private void readObject(java.io.ObjectInputStream s) throws java.io.IOException, ClassNotFoundException { elementData = EMPTY_ELEMENTDATA; // Read in size, and any hidden stuff s.defaultReadObject(); // Read in capacity s.readInt(); // ignored if (size > 0) { // be like clone(), allocate array based upon size not capacity ensureCapacityInternal(size); Object[] a = elementData; // Read in all elements in the proper order. for (int i=0; i<size; i++) { a[i] = s.readObject(); } } }
- He implemented Java io. Serializable
- He used the transient keyword on the field elementData array
- He also wrote the writeObject and readObject methods
If you use IDE to query and find that these two methods do not implement any interface, when will they be called? After consulting the data, we found that Java io. Serializable notes say
Classes that require special handling during the serialization and deserialization process must implement special methods with these exact signatures: <PRE> private void writeObject(java.io.ObjectOutputStream out) throws IOException private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException; private void readObjectNoData() throws ObjectStreamException; </PRE> ··· @author unascribed @see java.io.ObjectOutputStream @see java.io.ObjectInputStream @see java.io.ObjectOutput @see java.io.ObjectInput @see java.io.Externalizable @since JDK1.1
In other words, these two methods are special callback methods. When your entity class is very special and needs to be serialized manually, you can implement these two methods manually
Then you can return to the detail. ArrayList is the writeObject that loops the element data array
Manually serialize and deserialize objects
Hook methods supported by Serializable interface
Let's first look at the definition of jdk serialization interface
Classes that require special handling during the serialization and deserialization process must implement special methods with these exact signatures: <PRE> private void writeObject(java.io.ObjectOutputStream out) throws IOException private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException; private void readObjectNoData() throws ObjectStreamException; </PRE> ··· @author unascribed @see java.io.ObjectOutputStream @see java.io.ObjectInputStream @see java.io.ObjectOutput @see java.io.ObjectInput @see java.io.Externalizable @since JDK1.1
It tells us that we can write writeObject and readObject to serialize manually (not affected by keyword modification)
Serialized usage scenarios
- For example, the network transmission of common Java objects
- java small game development is more convenient to store complex relationships than xml when storing game data
It's a storage method. You can use it as long as you need it
summary
- Serialization uses Java io. Serializable interface
- Static fields are not serialized
- transient keyword for field masking
- Customize serialization to write readObject and writeObject methods
- The write order and read order should be consistent. Even if they are not used, they need to read