一直说序列化,但是为什么要实现序列化?它都实现了什么东西?在实际中的应用是什么?为什么实现接口也可以不定义序列码serialVersionUID的默认值?不定义序列码会出现什么问题?
Serializable的介绍如下
/**
* Serializability of a class is enabled by the class implementing the
* java.io.Serializable interface. Classes that do not implement this
* interface will not have any of their state serialized or
* deserialized. All subtypes of a serializable class are themselves
* serializable. The serialization interface has no methods or fields
* and serves only to identify the semantics of being serializable.
* To allow subtypes of non-serializable classes to be serialized, the
* subtype may assume responsibility for saving and restoring the
* state of the supertype's public, protected, and (if accessible)
* package fields. The subtype may assume this responsibility only if
* the class it extends has an accessible no-arg constructor to
* initialize the class's state. It is an error to declare a class
* Serializable if this is not the case. The error will be detected at
* runtime.
* During deserialization, the fields of non-serializable classes will
* be initialized using the public or protected no-arg constructor of
* the class. A no-arg constructor must be accessible to the subclass
* that is serializable. The fields of serializable subclasses will
* be restored from the stream.
* When traversing a graph, an object may be encountered that does not
* support the Serializable interface. In this case the
* NotSerializableException will be thrown and will identify the class
* of the non-serializable object.
当遍历一个图形时,可能会遇到不支持可序列化接口的对象。在此情况下,将抛出 NotSerializableException,并将标识不可序列化对象的类。
If a serializable class does not explicitly declare a serialVersionUID, then
* the serialization runtime will calculate a default serialVersionUID value
* for that class based on various aspects of the class, as described in the
* Java(TM) Object Serialization Specification. However, it is strongly
* recommended that all serializable classes explicitly declare
* serialVersionUID values, since the default serialVersionUID computation is
* highly sensitive to class details that may vary depending on compiler
* implementations, and can thus result in unexpected
* InvalidClassException
s during deserialization. Therefore, to
* guarantee a consistent serialVersionUID value across different java compiler
* implementations, a serializable class must declare an explicit
* serialVersionUID value. It is also strongly advised that explicit
* serialVersionUID declarations use the private
modifier where
* possible, since such declarations apply only to the immediately declaring
* class--serialVersionUID fields are not useful as inherited members. Array
* classes cannot declare an explicit serialVersionUID, so they always have
* the default computed value, but the requirement for matching
* serialVersionUID values is waived for array classes.
*
package com.yeepay.g3.app.watch.serial;
import com.alibaba.fastjson.JSONObject;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
/**
* 类名称: SerialMemo
* 类描述:
*
* @author: king
* @since: 16/8/24 下午2:03
* @version: 1.0.0
*/
public class SerializableTest {
//序列化操作--FileOutputStream
private static void start() throws IOException {
User user = new User("a", 6);
user.setPwd("123123");
System.out.println("序列化操纵之前");
System.out.println("user:" + user);
System.out.println("user:" + JSONObject.toJSON(user));
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("user"));
oos.writeObject(user);
oos.close();
}
//反序列化操作---FileInputStream
private static void end() throws IOException, ClassNotFoundException {
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("user"));
User user1 = (User) ois.readObject();
ois.close();
System.out.println("反序列化操作之后");
System.out.println("user1:" + user1);
System.out.println("user1:" + JSONObject.toJSON(user1));
}
public static void main(String[] args) throws IOException, ClassNotFoundException, CloneNotSupportedException {
// start();
end();
}
}
class User implements Serializable {
private static final long serialVersionUID = 6456715177298089050L;
private String name;
private int age;
private String pwd;
public User() {
System.out.println("create User");
}
public User(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getPwd() {
return pwd;
}
public void setPwd(String pwd) {
this.pwd = pwd;
}
}
序列化操纵之前
user:com.yeepay.g3.app.watch.serial.User@8e1dfb1
user:{"age":6,"name":"a","pwd":"123123"}
反序列化操作之后
user1:com.yeepay.g3.app.watch.serial.User@7796649
user1:{"age":6,"name":"a","pwd":"123123"}
//private static final long serialVersionUID = 6456715177298089050L;
序列化操纵之前
user:com.yeepay.g3.app.watch.serial.User@8e1dfb1
user:{"age":6,"name":"a","pwd":"123123"}
反序列化操作之后
user1:com.yeepay.g3.app.watch.serial.User@7796649
user1:{"age":6,"name":"a","pwd":"123123"}
我们会发现,serialVersionUID貌似别没有卵用,都执行通过了,但是事实真的如此么class User implements Serializable {
// private static final long serialVersionUID = 6456715177298089050L;
private String name;
private int age;
private String pwd;
class User implements Serializable {
// private static final long serialVersionUID = 6456715177298089050L;
private String name;
private int age;
private String pwd;
private String memo;
Exception in thread "main" java.io.InvalidClassException: com.yeepay.g3.app.watch.serial.User; local class incompatible: stream classdesc serialVersionUID = 3686252464883344796, local class serialVersionUID = 2579413800018730532
at java.io.ObjectStreamClass.initNonProxy(ObjectStreamClass.java:604)
at java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1601)
at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1514)
at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1750)
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1347)
at java.io.ObjectInputStream.readObject(ObjectInputStream.java:369)
at com.yeepay.g3.app.watch.serial.SerializableTest.end(SerializableTest.java:38)
at com.yeepay.g3.app.watch.serial.SerializableTest.main(SerializableTest.java:47)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:601)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:140)
private transient String pwd;// 标记属性
序列化操纵之前
user:com.yeepay.g3.app.watch.serial.User@650b5efb
user:{"age":6,"name":"a","pwd":"123123"}
反序列化操作之后
user1:com.yeepay.g3.app.watch.serial.User@49c0c8b3
user1:{"age":6,"name":"a"}
Exception in thread "main" java.io.NotSerializableException: com.yeepay.g3.app.watch.serial.Memo