JAVA 对象序列化
对象序列化:就是将那些实现了Serializable接口的对象转换成一个字节序列,并能够在以后将这个字节序列完全恢复为原来的对象。
对象的反序列化:
对象序列化的适用场景:
a)当想要把内存中的对象保存到一个文件中或者数据库中的时候,可以使用序列化;
b)当想要使用套接字/网络编程中在网络上传输对象的时候,需要实现序列化;
c)当想通过RMI(Remote Method Invocation,远程方法调用)的时候,实现序列化;(使得存活在其他计算机上的对象使用起来就像是存活在本地计算机上一样);
d)对于Java Beans来说,对象的序列化也是必须的。使用一个Bean时,一般情况下是在设计阶段对它的状态信息进行配置,这种状态信息必须保存下来,并在程序启动时进行后期恢复;这种工作就是由对象序列化完成。
序列化步骤
步骤一:创建一个对象输出流,它可以包装一个其它类型的目标输出流
步骤二:通过对象输出流的writeObject()方法写对象
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("a.out"));
oos.writeObject(myTest);
反序列化步骤
步骤一:创建一个对象输入流,它可以包装一个其它类型输入流
步骤二:通过对象输出流的readObject()方法读取对象:
oin=new ObjectInputStream(new FileInputStream("a.out"));
test=(SOlution) oin.readObject();
JAVA代码
package test;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
public class SOlution implements Serializable{
private static final long serialVersionUID = 1L;
private String name="fishing_fly";
private static int age=25;
public static void start(){
new SOlution().name="xupu";//普通成员变量只能通过新建实例进行复制调用
age=1;//静态成员变量可以直接复制
ObjectInputStream oin=null;
try{
oin=new ObjectInputStream(new FileInputStream("a.out"));
}
catch(FileNotFoundException e1){
e1.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
SOlution test=null;
try {
test=(SOlution) oin.readObject();
} catch (ClassNotFoundException | IOException e) {
e.printStackTrace();
}
System.out.println("test.name="+test.name);//因为读出的对象的name=fishing_fly
System.out.println("test.age="+test.age);//为何把最上面代码的age变量添上static 后还是反序列化出了24呢?
//而新的从新对变量赋值的代码,不是static的得到了序列化本身的值
//,而static的则得到的是从新附的值。原因: 序列化会忽略静态变量,
//即序列化不保存静态变量的状态。静态成员属于类级别的,
//所以不能序列化。即 序列化的是对象的状态不是类的状态。
//这里的不能序列化的意思,是序列化信息中不包含这个静态成员域。
}
public static void main(String[] args){
try
{
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("a.out"));//输出流保存的文件名为 a.out ;ObjectOutputStream能把Object输出成Byte流
SOlution myTest=new SOlution();
oos.writeObject(myTest);
oos.flush(); //缓冲流
oos.close(); //关闭流
} catch (FileNotFoundException e)
{
e.printStackTrace();
} catch (IOException e)
{
e.printStackTrace();
}
start();//调用下面的 反序列化 代码
}
}
输出结果
test.name=fishing_fly
test.age=1
总结一下序列化的使用:
,子类自动实现序列化,不需要显式实现Serializable接口;
当一个对象的实例变量引用其他对象,序列化该对象时也把引用对象进行序列化;
static,transient后的变量不能被序列化;