一、什么是序列化,为什么要序列化,序列化解决了什么问题
二、怎样实现java的序列化以及重点
三、序列化的识别
一、什么是序列化,为什么要实现java的序列化
0、序列化:将对象数据直接转换成字节流数据保存起来,并且在以后恢复成对象的过程
1、存储对象的状态,直接将对象的状态保存到文件里面,eg:保存游戏人物的状态
2、为了解决当存储一个对象的时候,如果存在另外的一个对象的引用时的存储问题
二、怎么实现java序列化以及重点
1、具体实现(让类实现Serializable接口)
package com.chenrui.serializable1;
import java.io.Serializable;
/**
* 游戏里面的任务状态类(headFirst java 上面的例子)
* */
public class GameCharacter implements Serializable{
private int power;//血量
private String name;//人物的姓名
private String type;//任务的种类
private String[] weapons;//武器
public GameCharacter(int power,String name,String type,String[] weapons) {
super();
this.power = power;
this.type = type;
this.weapons = weapons;
this.name = name;
}
@Override
public String toString() {
StringBuffer sb = new StringBuffer();
sb.append("name is "+name+" ");
sb.append("power is "+this.power+" ");
sb.append("type is "+this.type+" ");
sb.append("weapon is ");
for(String weapon : this.weapons) {
sb.append(weapon+" ");
}
return sb.toString();
}
}
2、测试类
package com.chenrui.serializable1;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
/**
* 游戏人物状态保持的模拟
* */
public class GameSaveTest {
public static void main(String[] args) throws ClassNotFoundException {
//任务的生成模拟
GameCharacter jintian = new GameCharacter(100,"景天","剑士",new String[]{"长剑","盾牌","轻灵战靴"});
GameCharacter lixiaoyao = new GameCharacter(100,"李逍遥","剑士",new String[]{"天剑","多兰之盾","急行战靴"});
GameCharacter zhaolinger = new GameCharacter(100,"赵灵儿","法师",new String[]{"天蛇杖","兰顿","水银战靴"});
//这里是战斗的代码
//现在玩家要退出,这里是保存他们的数据的代码,将对象保存起来
try {
FileOutputStream fos = new FileOutputStream("仙剑save.txt");//生成一个节点流
ObjectOutputStream oos = new ObjectOutputStream(fos);//生成ObjectOutputStream过滤流
oos.writeObject(jintian);//将数据写入ObjectOutPutStream;
oos.writeObject(lixiaoyao);
oos.writeObject(zhaolinger);
oos.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//这个是退出游戏与重新登陆时的状态
jintian = null;
zhaolinger = null;
lixiaoyao = null;
//这里的就是重写读取数据,获得保存之前的状态(解序列化)
try {
FileInputStream fis = new FileInputStream("仙剑save.txt");
ObjectInputStream ois;
ois = new ObjectInputStream(fis);
jintian = (GameCharacter)ois.readObject();
lixiaoyao = (GameCharacter)ois.readObject();
zhaolinger = (GameCharacter)ois.readObject();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//接下来就是输出测试
System.out.println(jintian.toString());
System.out.println(lixiaoyao.toString());
System.out.println(zhaolinger.toString());
}
}
3、过程简析:
(1)要保存对象所对应的类实现Serializable接口
(2)将对象保存的过程
1、生成一个节点输出流
2、生成一个ObjectOutputStream,他链接到上面的节点流
3、写对象
4、用到的接口与类
(1)Serializable接口
(2)ObjectOutStream类以及里面的writeObject方法,这个类实现了ObjectOutput接口
5、序列化的注意事项:
(1)在序列化时,static类型的变量时不会别保存的。因为这个变量时属于类的,而不是属于当个对象的
(2)在序列化时,如果希望某些变量不被保存,可以再声明的时候加上transient关键字,
6、重点
(1)在对象被序列化时,被该对象引用的实例变量也会被序列化,且所有被引用的对象也会被序列化(前提示被引用的对象所对应的类都实现了Serializable接口),如果有
俩个引用指向的是同一个对象,这个时候只保存一个对象。
(2)在序列化的过程中,ObjectOutStream的作用是把对象转化为可以写入串流的数据,FileOutputStream等节点流负责将数据写入文件。
7、解序列化
(1)创建FileInputStream
(2)创建ObjectInputStream
(3)读取对象,使用readObject()方法,这里是根据写入的顺序进行读取
(4)转换对象类型
(5)关闭ObjectInputStream;
深入解析:
(1)把对象从Stream读取出来
(2)jvm通过存储的信息判断对象的类型
(3)jvm尝试寻找和加载对象的类,如果无法找到或者是无法加载,则会抛出异常
(4)新的对象被配置到堆上,但是构造函数不会执行。
(5)对象的实例变量会被还原成序列化时点的状态,transient变量会被赋值为null,
三、序列化的识别
1、如果对象被序列化后,要解序列化,必须保证在解序列化之前没有进行损害序列化的修改。
2、serialVersionUID:当对象被序列化的时候,该对象将会获得一个根据类的结构信息而生成的seriaVersionUID,java尝试要还原对象的时候,它会比对对象与jvm上类的serialVersionUID.如果版本不相同,将会抛出异常。