一、序列化的概念
序列化 (Serialization) 是将对象的状态信息转换成可以存储或传输的形式的一个过程。在序列化期间,对象将其当前状态写入到临时或持久性存储区。以后,可以通过从存储区中读取或反序列化对象的状态,重新创建该对象。序列化使其他代码可以查看或修改那些不序列化便无法访问的对象实例数据。确切地说,代码执行序列化需要特殊的权限。
通常,对象实例的所有字段都会被序列化,这意味着数据会被表示为实例的序列化数据。这样,能够解释该格式的代码有可能能够确定这些数据的值,而不依赖于该成员的可访问性。类似地,反序列化从序列化的表示形式中提取数据,并直接设置对象状态,这也与可访问性规则无关。
Java 的对象序列化,就是把一个对象变为二进制的数据流的一种方法,通过对象序列化可以方便的实现对象的传输或存储。
如果一个类的对象想被序列化,则对象所在的类就必须实现 java.io.Serializable 接口(此接口属于标识接口,表示具备某种能力),接口的定义如下:
public interface Serializable{}
对象序列化示例代码如下:
import java.io.Serializable;
import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStream;
import java.io.ObjectOutputStream;
class Person implements Serializable
{
//通过判断类的serialVersionUID来验证版本一致性
private static final long serialVersionUID = 1L;
private String name ;
private int age ;
public Person(String name, int age)
{
this.name = name;
this.age = age;
}
public String toString()
{
return "姓名:" + this.name + ",年龄:" + this.age;
}
}
public class SerDemo
{
public static void main(String[] args) throws Exception
{
File f = new File("d:" + File.separator + "test.txt");//定义保存路径
OutputStream out = new FileOutputStream(f);
ObjectOutputStream oos = null;//声明对象输出流
oos = new ObjectOutputStream(out);
oos.writeObject(new Person("张三",30));//保存对象
oos.close();//关闭操作流
}
}
二、反序列化
要想完成对象的输入和输出,必须依靠对象输出流(ObjectOutputStream)和对象输入流(ObjectInputStream)。
使用对象输出流输出序列化对象的步骤,有时也称为序列化,而使用对象输入流读入对象的过程,有时也称为反序列化。
所有的对象拥有各自的属性值(private),但是所有的方法都是公共的(public),所以序列化对象的时候实际上序列化的就是属性。
对象反序列化示例代码如下:
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.ObjectInputStream;
public class SerDemo02
{
public static void main(String[] args) throws Exception
{
File f = new File("d:" + File.separator + "test.txt");
ObjectInputStream ois = null;//声明对象输入流
InputStream input = new FileInputStream(f);
ois = new ObjectInputStream(input);
Object obj = ois.readObject();//读取对象
System.out.println(obj);
input.close();//关闭操作流
ois.close();//关闭操作流
}
}
Java 的序列化机制是通过判断类的 serialVersionUID 来验证版本一致性的。在进行反序列化时,JVM 会把传来的字节流中的 serialVersionUID 与本地相应实体类的 serialVersionUID 进行比较,如果相同就认为是一致的,可以进行反序列化,否则就会出现序列化版本不一致的异常,即是 InvalidCastException。
具体的序列化过程:在序列化操作的时候系统会把当前类的 serialVersionUID 写入到序列化文件中,当反序列化时系统会去检测文件中的 serialVersionUID,判断它是否与当前类的 serialVersionUID 一致,如果一致就说明序列化类的版本与当前类版本是一样的,可以反序列化成功,否则失败。
注意:对于任何可能包含重要的安全性数据的对象,如果可能,应该使该对象不可序列化。如果它必须为可序列化的,请尝试生成特定字段来保存不可序列化的重要数据。如果无法实现这一点,则应注意该数据会被公开给任何拥有序列化权限的代码,并确保不让任何恶意代码获得该权限。
三、Externalizable接口
被 Serializable 接口声明的类,其对象的内容都将被序列化,如果现在用户希望可以自己指定序列化的内容,则可以让一个类实现 Externalizable 接口,此接口的定义如下:
public interface Externalizble extends Serializable
{
public void writeExternal(ObjectOutput out)throws IOException;
public void readExternal(ObjectInput in)throws IOException,ClassNotFoundException;
}
注意:在使用 Externalizable 接口的时候需要在被序列化的类中定义一个无参构造方法,因为此接口在进行反序列化的时候,回先使用类中的无参构造方法为其进行实例化,之后再将内容设置到属性之中。
实例代码如下:
import java.io.*;
class Person01 implements Externalizable{
private static final long serialVersionUID = 1L;
private String name;
private int age;
public Person01(){}//无参构造
public Person01(String name, int age){
this.name = name;
this.age = age;
}
public String toString(){
return "姓名:" + this.name + ",年龄:" + this.age;
}
public void writeExternal(ObjectOutput out) throws IOException {
out.writeObject(name);//保存姓名属性
out.writeInt(age);//保存年龄属性
}
public void readExternal(ObjectInput in) throws IOException,
ClassNotFoundException {
this.name = (String)in.readObject();//读取姓名,向下转型
this.age = in.readInt();//读取年龄
}
}
public class SerDemo03 {
public static void main(String[] args) throws Exception{
ser();
dser();
}
//序列化对象
public static void ser() throws Exception{
File f = new File("d:" + File.separator + "test.txt");//定义保存路径
OutputStream out = new FileOutputStream(f);
ObjectOutputStream oos = null;//声明对象输出流
oos = new ObjectOutputStream(out);
oos.writeObject(new Person01("张三",30));//保存对象
oos.close();//关闭
}
//反序列化对象
public static void dser() throws Exception{
File f = new File("d:" + File.separator + "test.txt");
ObjectInputStream ois = null;//声明对象输入流
InputStream input = new FileInputStream(f);
ois = new ObjectInputStream(input);
Object obj = ois.readObject();
ois.close();
input.close();
System.out.println(obj);
}
}
https://www.cnblogs.com/skjsg/p/4686411.html
http://blog.csdn.net/zcl_love_wx/article/details/52126876