Serializable interface object serialization and

Object Serialization

Refers to the target sequence of Java objects stored as a binary file byte code, deserialization means converts binary byte code files into Java objects.

Consider a class the Person, implements the serialization interface

@Setter
@Getter
@AllArgsConstructor
public class Person implements Serializable {
    private String name;
    private Integer age;
}

It can be read and written by the object ObjectInputStream and ObjectOutputStream.

//序列化
FileOutputStream fileOutputStream = new FileOutputStream("person");
ObjectOutputStream objectOutputStream = new ObjectOutputStream(fileOutputStream);
objectOutputStream.writeObject(new Person("厂长", 27));
objectOutputStream.close();
//反序列化
FileInputStream fileInputStream = new FileInputStream("person");
ObjectInputStream objectInputStream = new ObjectInputStream(fileInputStream);
Person person = (Person) objectInputStream.readObject();
objectInputStream.close();
System.out.println(person); System.out.println(person.getName()+"——"+person.getAge());
 

objectOutputStream binary output of the Person object class, ObjectInputStream to the information of the object acquired by reading a binary file.

 

It can be seen serialization is one way to achieve object persistence and object information in this way can be saved to disk or transmitted through the network binary file format.

commons-lang package provides a sequence of tools SerializationUtils, the sequence can be achieved and deserialize serialize () and Deserialize () method.

 public static void serialize(Serializable obj, OutputStream outputStream)

You can see the incoming class of objects need to achieve Serializable interface.

Serializable Interface

Serializable interface is a marker interface. Marker interface means that there is no interface methods and properties. It only shows that its implementation class belongs to a particular type, it can be the type of query with instanceof.

if(person instanceof Serializable)

As well as other commonly used marker interface Cloneable interface.

During serialization, will determine whether or not to be serialized class is String, Enum, Array or type Serializable, otherwise it will throw an exception NotSerializableException

            if (obj instanceof String) {
                writeString((String) obj, unshared);
            } else if (cl.isArray()) {
                writeArray(obj, desc, unshared);
            } else if (obj instanceof Enum) {
                writeEnum((Enum<?>) obj, desc, unshared);
            } else if (obj instanceof Serializable) {
                writeOrdinaryObject(obj, desc, unshared);
            } else { if (extendedDebugInfo) { throw new NotSerializableException( cl.getName() + "\n" + debugInfoStack.toString()); } else { throw new NotSerializableException(cl.getName()); } } 

 

Implements Serializable class interface, indicating that the class is serializable. If some of the fields of the class does not need to be serialized, transient modification may be used.

transient int age

Note: Due to static members do not belong to the object instance, so it will not be serialized, serialization is for the object.

 

Another usage scenario is often used as a hash redisTemplate store the object type, the object needs to be stored to achieve serializable.

The hash redis types are stored in a string type, by way of a sequence of objects can be in the form of binary byte string type is stored as a code.

<HK> byte[] rawHashKey(HK hashKey) {
        Assert.notNull(hashKey, "non null hash key required");
        return this.hashKeySerializer() == null && hashKey instanceof byte[] ? (byte[])((byte[])hashKey) : this.hashKeySerializer().serialize(hashKey);
    }

It can be seen that, if the incoming hashKey by this.hashKeySerializer (). Serialize () method is converted into byte [] type.

 

To ensure the correctness of the sequence of the data before and after

Full class name (package name + class name) object before 1. deserialize and serialize objects must be consistent, otherwise it will throw ClassNotFoundException.

2. deserialized object needs to be consistent and serialVersionUID before and serialized objects serialVersionUID, otherwise it will throw InvalidClassException.

serialVersionUID

Class needs to be serialized version added serialVersionUID, to authenticate a serialized object deserialization process and whether the received version number are the same object class.

Explicit generally set private static final long serialVersionUID = 1L, or the system automatically generates a 64-bit hash field, based on the class name, class and its property modifiers, interfaces and interface sequence, attributes, static initialization, constructors generation, resulting in a change to any one of the system-generated serialVersionUID change.

If not explicitly defined serialVersionUID, based on the Java serialization mechanism compiled classes (the class is related to the above-related properties), the automatic generation of a unique serialized version serialVersionUID for comparison,

If there is no change in the class structure, serialVersionUID will not change;

But if the class structure changes, such as changing the attribute name, attribute modifiers changed, etc., will result in a mismatch serialVersionUID, which can not be achieved deserialization.

(After testing, comments will not affect the class structure, it seems, and compiler related, some of the conclusions of the Internet seems to be a space will affect comment)

 In addition, different java compiler may generate a different serialVersionUID values, generate InvalidClassException should not be there.

So, if you do not want to force through a version of the compiler classification plan, and want to achieve class to serialize interface compatible with a previous version, you need to declare serialVersionUID display, as long as serialization and de-serialization of the class of incoming byte stream to ensure consistent serialVersionUID, they are possible to achieve deserialization.

Note: The so-called compatible, for example, if deserialize incoming analogy of the original sequence to achieve a multi-class field, then the field will be ignored; if deserialize incoming analogy of the original sequence to achieve a small class field, which will be assigned to the default value of the corresponding type.

* Custom serialization

If desired, the method may be used to read and write a custom, this scenario is relatively rare, the Internet, said implement serialization if class is a singleton, then it should custom serialization mode, specify the same single embodiment.

You can customize the serialization strategy in two ways.

One is the Serializable class implements the interface, define two methods

private void writeObject(ObjectOutputStream stream) throws IOException
private void readObject(ObjectInputStream stream) throws IOException,ClassNotFoundException

 ObjectInput and OutputStream class checking whether there is reflected by writeObject () in the serialization / deserialization time and readObject () method,

If there is an object of the class writeObject and readObject method is called serialization operation.

* Embodied by the passing objects ObjectStreamClass lookupStreamClass () method

ObjectStreamClass clDesc = ObjectStreamClass.lookupStreamClass(objClass);

 

In createClassDesc therein (Cl) method, checking whether there is overwritten by reflecting the bean

result.methodWriteObject = findPrivateMethod(cl, "writeObject", WRITE_PARAM_TYPES);
result.methodReadObject = findPrivateMethod(cl, "readObject", READ_PARAM_TYPES);

 

Another way is to achieve a Externalnalizable Interface

writeExternal(ObjectOutput out)) 和 readExternal(ObjectInput in)

 This interface also use less, not yet written a fine.

Guess you like

Origin www.cnblogs.com/gss128/p/11028572.html