Java序列化与反序列化
序列化:指将对象的状态数据以字节流的形式进行处理,在文件中长期存储。
反序列:从字面上就能知道,指的就是在需要的时候从文件中获取该对象的信息以重新获得一个完全的对象。
作用:
(1)永久性保存对象,把对象通过序列化字节流保存到本地文件中。
(2)通过序列化在网络中传递对象
(3)通过序列化在进程间传递对象
一、实现序列化功能的两种接口
(1)Serializable接口
(2)Externalizable接口:该接口继承了Serializable接口,是对Serializable的扩展,并提供了readExternal(ObjectInput in)和writeExternal(ObjectOutout out)两种方法,通过重写这两个方法来实现自身的序列化行为的控制。在对实现了Externalizable的类的对象进行反序列化时,会先调用该类的无参构造函数,若无参构造函数被删除或被设置为private、default或protected时会抛出java.io.InvalidException:no valid construction等
二、对象的序列化
- 序列化实现步骤:
(1)需要序列化的对象所属类必须实现Serializable接口;
(2)构造FileOutputStream对象;
(3)构造ObjectOutputStream对象;
(4)使用ObjectOutputStream对象的writeObject()方法进行序列化;
(5)关闭ObjectOutputStream对象;
(6)关闭FileOutputStream对象;
(7)对序列化全程捕获IOException; - 反序列化实现步骤:
(1)需要序列化的对象所属类必须实现Serializable接口;
(2)构造FileInputStream对象;
(3)构造ObjectInputStream对象;
(4)使用ObjectInputStream对象的readObject()方法进行序列化;
(5)关闭ObjectInputStream对象;
(6)关闭FileInputStream对象;
(7)对序列化全程捕获ClassNotFoundException和IOException; 注意:
1.只有实现了Serializable或Externalizable的类的对象才可以实现序列化。
- 2.对象和对象数组都可以实现序列化
- 3.若一个父类实现了Serializable或Externalizable接口,其子类均实现了Serializable或Externalizable接口。
- 4.实现Serializable或Externalizable接口的类应提供无参构造函数
- 5.static的属性和方法不能被序列化,因为static的属性和方法与对象无关,而序列化和反序列化则是针对对象而言的。
- 6.对于不希望被序列化的非static成员和方法可以使用transient关键字标明
- 7.若一个序列化子类的父类是非序列化的,则该子类从父类继承下来的变量将恢复其默认初始值而不被初始化。
实例代码:
(1)实现了Serializable接口对象:
import java.io.Serializable;
//实现了Serializable接口的Student类
public class Student implements Serializable{
private String Sname;
private String Sex;
private int age;
public Student() {
// TODO 自动生成的构造函数存根
}
public Student(String Sname,String Sex,int age){
this.Sname=Sname;
this.Sex=Sex;
this.age=age;
}
public String getSname() {
return Sname;
}
public String getSex() {
return Sex;
}
public int getAge() {
return age;
}
}
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 testSers {
public static void main(String[] args) {
// TODO 自动生成的方法存根
Student stu=new Student("Mike", "male", 22);
serialize("C:\\student.dat", stu);
System.out.println("序列化完毕");
Student stu1=deserialize("C:\\student.dat");
System.out.println(stu1.getSname()+"\t"+stu1.getSex()+"\t"+stu1.getAge());
System.out.println("反序列化完毕");
}
public static void serialize(String filename,Student stu){
try {
FileOutputStream fout=new FileOutputStream(filename);
ObjectOutputStream oout =new ObjectOutputStream(fout);
oout.writeObject(stu);
oout.close();
fout.close();
} catch (FileNotFoundException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
} catch (IOException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}
}
public static Student deserialize(String filename){
try {
FileInputStream fin=new FileInputStream(filename);
ObjectInputStream oin=new ObjectInputStream(fin);
Student stu=(Student)oin.readObject();
oin.close();
fin.close();
return stu;
} catch (FileNotFoundException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
} catch (IOException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
} catch (ClassNotFoundException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}
return null;
}
}