Serialization and deserialization
Serialization is the process of converting a data structure or object into a binary string;
Deserialization is the process of converting serialized binary strings into data structures or objects.
The purpose of serialization and deserialization is to facilitate network transmission and data persistence.
Common serialization and deserialization data formats include JSON and XML, and JSON is the most widely used in Android.
Second, Serializable interface
This interface is the serialization interface provided by Java, which is an empty interface; A class that wants to be serialized by ObjectOutputStream and deserialized by ObjectInputStream needs to implement the Serializable interface. The real serialization and deserialization are done through the writeObject and readObject methods.
1. SerialVersionUID uniquely identifies a serializable class. When implementing our own serializable class, it is best to manually define a serialVersionUID variable and set it to private and final. If we do not set this value manually, then we will change a class after serialization and an error will occur during deserialization because the serialVersionUID value automatically calculated by the program will be different from the previous one, causing class version incompatibility issues.
2. For Serializable classes, attributes that do not implement the Serializable interface cannot be serialized or deserialized; When a class is deserialized, its non-serializable property is recreated by calling its no-argument constructor. Therefore, the no-argument constructor for the property must exist or an error will be reported.
If a class implements serialization, its subclasses can also be serialized.
4. The member variable modified with transient keyword does not participate in serialization, and the field is set to the initial value during deserialization;
5. Static variables are classes, not objects, and therefore do not participate in serialization; Object serialization stores the state of the object, its member variables, so serialization doesn’t care about static variables;
The Externalizable interface inherits from the Serializable interface. We can implement this interface to make our class Serializable. There are two methods to implement this interface: writeExternal and readExternal. We implement our own serialization logic in these two methods. For example, if we want to serialize a few fields, we can write them in these two methods.
ReadObject /writeObject Process Analysis: Take writeObject as an example
The real serialization and deserialization operations are carried out through writeObject method and readObject method. The following is the process analysis of writeObject.
WriteObject () is called because enableOverride is set to Fasle in the constructor of ObjectOutputStream.
public final void writeObject(Object obj) throws IOException {
if (enableOverride) {
writeObjectOverride(obj);
return;
}
writeObject0(obj, false);
、、、
}
Copy the code
Since our class implements the Serializable interface, writeObject0 calls writeOrdinaryObject.
private void writeObject0(Object obj, Boolean unshared) throws IOException {,,, and else if (obj instanceof Serializable) {writeOrdinaryObject(obj, desc, unshared); }}Copy the code
If our class implements the Externalizable interface, the writeExternalData method will be called; otherwise, the writeSerialData method will be called.
private void writeOrdinaryObject(Object obj,ObjectStreamClass desc,boolean unshared){
if (desc.isExternalizable() && !desc.isProxy()) {
writeExternalData((Externalizable) obj);
} else {
writeSerialData(obj, desc);
}
}
Copy the code
If we override the writeSerialData method in our own class, we will call our own writeSerialData method. If not, the defaultWriteFields method is called to serialize the individual fields; In the defaultWriteFields method, basic type fields and object fields are processed separately.
private void writeSerialData(Object obj, ObjectStreamClass desc){
if (slotDesc.hasWriteObjectMethod()) {
、、、
}else {
defaultWriteFields(obj, slotDesc);
}
}
Copy the code
5. We can override the readObject,writeObject, readResolve, and writeReplace methods in the Serializable interface class to define our own serialization logic. The call sequence is writeReplace before writeObject and readResolve after readObject.
4. Parcelable interface
Serializable is a standardized serialization interface provided by Java, while Parcelable is a serialization interface provided by Android. The use of Parcelable is relatively complex, but much more efficient. Parcelable is provided by the AndroidSDK, it is based on memory, because the memory read and write speed is higher than the hard disk, so the cross process object transfer in Android generally use Parcelable;
Use: Parcelable interface, need to rewrite writeToParcel method; You need to create a Parcelable.Creator object;
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(this.name);
dest.writeFloat(this.score);
}
public static final Parcelable.Creator<Course> CREATOR = new Parcelable.Creator<Course>()
Copy the code
Summary of typical problems:
1, Parcelable and Serializable comparison:
Serializable Operates on hard disks through I/O, with a slow speed, unlimited size, and extensive use of reflection to generate fragments. Parcelable operates directly in memory, which is efficient and cannot exceed 1 MB in size.
2. Why Bundle design in Android instead of Map structure
In Android, if an Intent is used to carry data, the data needs to be of either a basic or Serializable type. HashMap Serializable, and Bundle Serializable Parcelable. On The Android platform, it is recommended to serialize using Parcelable, so the system encapsulates the Bundle.
3. Why can’t IntEnts pass objects directly between components rather than through serialization?
When launching another component with an Intent, data needs to be transferred between different processes. We know that objects cannot be transferred between processes directly, so we need to serialize them. In Android, Parcelable is preferred.
5. Basic Json parsing
Json is a lightweight data interchange format; Fast reading and writing speed, simple parsing, lightweight, independent of language and platform, good description; Json and Javabean can be interchanged through parsers, serialization and deserialization, commonly used parsers are Gson and FastJson.
The COMMON JSON parsing method is used
Gson resolution:
JSON data can be automatically parsed into a Person object with a simple call to the following code:
Gson gson = new Gson();
Person person = gson.fromJson(jsonData,Person.class);
If we need to parse a JSON array, we need to use TypeToken to pass the data type we want to parse into fromJson:
List list = gson.fromJson(jsonData,new TypeToken<List(){}.getType());
If you need to convert a person object toJson data, you can simply use the toJson method:
String jsonData = gson.toJson(person);
FastJson resolution:
To convert a Javabean to JSON data, simply call the following methods and pass parameters to collections:
String jsonData = JSON.toJSONString(person);
If you want to convert JSON data into Javabeans, you simply call the following methods:
Person person = JSON.parseObject(jsonData,Person.class);
If you want to convert to more complex objects, such as collections, you can use the following methods:
List list = JSON.parseObject(jsonData,new TypeReference<List>(){});