Some notes and suggestions for serialization

This article is from "151 Suggestions for Improving Java"


Recommendation 11: Develop a good habit of showing the declaration UID



Let's first write a serialization and deserialization tool class SerilizationUtils

public class SerializationUtils {

	private static String FILE_NAME="E:/serializable.txt";
	
	public static void writeObject(Serializable s){
		try{
			
			
			ObjectOutputStream oob = new ObjectOutputStream(new FileOutputStream(FILE_NAME));
			oob.writeObject(s);
			oob.close();
		}catch(Exception e){};
	}
	
	public static Object readObject(){
		Object obj=null;
		try{
			
			ObjectInputStream oob = new ObjectInputStream(new FileInputStream(FILE_NAME));
			obj = oob.readObject();
			
			oob.close();
		}catch(Exception e){};
		
		return obj;
	}
}

Person class

public class Person implements Serializable  {

	/**
	 * The declaration UID not displayed here
	 */
	//private static final long serialVersionUID = 1L;

	private String name;

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}
	
	//
	/*private String sex;

	public String getSex() {
		return sex;
	}

	public void setSex(String sex) {
		this.sex = sex;
	}*/
	
}

First define a message producer Produce

public class Produce {

	public static void main(String[] args){
		
		Person person = new Person();
		person.setName("Shi Renchuang");
		
		//after adding sex
		//person.setSex("Male");
		//Serialize and save to disk

		SerializationUtils.writeObject(person);
		System.out.println(person);
	}
}

After the execution here, the person is serialized to E:/serializable.txt


then define a consumer

public class Consumer {
	
	public static void main(String[] args) throws Exception{
		
		// deserialize
		Person p = (Person)SerializationUtils.readObject();
		System.out.println("The value obtained by deserialization"+p.getName());
		//System.out.println("The value obtained by deserialization"+p.getSex());
	}

}

There is no problem with running it here; but what happens if we do not refer to a Person when serializing and deserializing;

For example, before serialization, person still has only one attribute name after executing produce (serialization); add a sex attribute to person (be careful not to run produce (serialization) again);

After adding the property we run the consumer (deserialize); an error occurs

The book says InvalidClassException error; but I personally reported the above error;

Why is this so?

The reason is that the version of the class (person) corresponding to serialization and deserialization is inconsistent; the JVM cannot convert the data stream into an instance object;

How does the JVM determine the corresponding version of a class?

Is through the SerivalVersionUID, that is, the stream identifier, that is, the version definition of the class

private static final long serialVersionUID = 1L;

UIDs can be implicitly declared and explicitly declared; implicit declarations are automatically generated by the compiler Basic listings are unique; if the class is changed; it is the UID that also changes

When deserializing, jvm will compare whether the UID in the data stream is consistent with the current class (person); if it is consistent, it means that the class has not changed; if it is inconsistent, it means that it has changed, which is a good validation mechanism;



However; there are special cases; for example: my class doesn't change much, and I want it to be serialized when deserializing as well. then what should we do?


Since we are judging whether the UIDs are consistent, we can make their UIDs consistent. Displaying the declared UIDs can solve this problem very well;


Recommendation 12: Avoid using serialized classes without final assignment of invariants in constructors


  

private static final long serialVersionUID = 1L;
	
	//final constant is a direct quantity. It will be recalculated when deserializing to keep the new and old unification of final objects, which is conducive to the unification of code business logic
	
	public final String testFinal="Before serialization";
// public final String testFinal="After serialization";

The assignment to testFinal during serialization is before serialization           

After serialization, change testFinal to After serialization   

then perform deserialization

	// deserialize
		Person p = (Person)SerializationUtils.readObject();
		
		System.out.println("Deserialized value: "+p.testFinal);
Is the output value before or after serialization? 

The output result is: the value obtained by deserialization: after serialization


why? During serialization, we serialized testFinal into a data stream and stored it on disk. It stands to reason that when deserializing, we get the value before serialization. Why did it become after serialization?


This is because of one of the basic rules of serialization: keep final new and old objects the same. Conducive to the unification of code business logic; that is, if final is a direct quantity, final will be recalculated during deserialization;


Another assignment of final variables: constructor assignment


public final String testFinal;

	public Person() {
		// TODO Auto-generated constructor stub
		testFinal="Before constructor assignment";
	}

Modification after serialization
testFinal="After constructor assignment";
Then deserialize; guess: the output here should be after the constructor assignment, right? Because rule 1 is the same!

So what is the output?

Deserialized value: before constructor assignment

Why before and not after the change? The reason is another rule


Constructor is not executed when deserializing!


Recommendation 13: Avoid complex assignments to final variables



Summary: Deserialization cannot be reassigned in the following cases


1. Assign value to final variable through constructor

2. Assignment of non-final variables through methods

3. The object modified by final is not the basic object


Recommendation 14: Use private methods of serialization classes to cleverly solve  some property   persistence problems


......


Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325895768&siteId=291194637