序列化与反序列化:
1.概念:
序列化:将对象的状态存储到特定介质的过程。也就是将对象的状态转换为可传输(流)的过程!
序列化 -------》 写入(输出流)
反序列化:从特定存储介质中读取数据并重新构建成对象的过程!也就是把流解析成对象的方式!
反序列化------》读取 (输入流)
2.关键对象
-
序列化:ObjectOutputStream,输出流对象.writeObject(自定义类的对象/集合);
-
反序列化:ObjectInputStream,输入流对象.readObject()
-
注意:序列化必须要实现Serializable接口,反序列化要进行强制类型转换,因为返回的是一个Object类型的对象!
3.代码如下
//学生类:实现了序列化接口Serializable
public class Student implements Serializable{
private int id;
private String name;
private String pwd;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPwd() {
return pwd;
}
public void setPwd(String pwd) {
this.pwd = pwd;
}
public Student() {
}
public Student(int id,String name,String pwd ) {
this.id=id;
this.name=name;
this.pwd=pwd;
}
/**
* 重写toString 方法
*/
public String toString() {
return "学号:" + id + ", 姓名:" + name + ", 密码:" + pwd;
}
}
//测试类:
public class Test {
public static void main(String[] args) {
//创建集合对象
ArrayList <Student> list=new ArrayList<Student>();
//创建学生类对象
Student stu1=new Student(11,"张三","123456");
Student stu2=new Student(12,"李四","024966");
Student stu3=new Student(13,"王五","386436");
//添加集合对象
list.add(stu1);
list.add(stu2);
list.add(stu3);
//声名序列化对象,
ObjectOutputStream oos=null;
ObjectInputStream ois=null;
try {
//1.序列化
//创建序列化对象输出流,写入数据
oos=new ObjectOutputStream(new FileOutputStream("学生.txt"));
//写入对象(集合)
oos.writeObject(list);
//2.反序列化
//创建反序列化对象输入流,读取数据
ois=new ObjectInputStream(new FileInputStream("学生.txt"));
//读取集合中的对象,得到的是Object类型
Object obj=ois.readObject();
//将集合中的obj类型强制转换成Student类型
ArrayList<Student> stuList=(ArrayList<Student>) obj;
//循环读取集合中的对象
for (int i = 0; i < list.size(); i++) {
Student stu=stuList.get(i);
System.out.println(stu);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} finally {
try {
//关闭流
ois.close();
oos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
输出结果:
注意:
- 如果出于安全考虑,某些属性要限制不能序列化,就需要使用transient关键字修饰属性!
- 如果在向文件中使用序列化机制写入多个对象,那么反序列化恢复对象时,必须按照写入的顺序读取。
- 如果一个可序列化的类,有多个父类(包括直接或者间接父类),则这些父类要么是可序列化的,要么有无参构造器,否则会抛出异常!
4.对象引用的序列化:
- 所有保存到磁盘中的对象都有一个序列号
- 当程序视图序列化一个对象时,将会检查是否已经序列化,只有序列化后的对象才能被转换成字节序列输出,否则报NotSerializableException异常
- 如果对象已经被序列化,则程序直接输出一个序列化编号,而不再重新序列化。