对象序列化概述
通过使用ObjectInputStream和ObjectOutputStream类保存和读取 对象的机制叫做序列化机制
对象(Object)序列化是指将对象转换为字节码序列的过程
反序列化则是根据字节码序列恢复对象的过程
序列化一般用于以下场景:
- 永久性保存对象,保存对象的字节序列到本地文件中
- 通过序列化对象在网络中传递对象
- 通过序列化在进程间传递对象
支持序列化的接口和类
- ObjectOutputStream : 提供序列化对象并把其写入流的方法
- ObjectInputStream : 读取流并反序列化对象
- Serializable接口:一个对象想要被序列化,那么它的类就要实现 此接口,这个对象的所有属性(包括private属性、包括其引用的对象)都可以被序列化和反序列化来保存、传递。
- Externalizable接口 : 他是Serializable接口的子类,有时我们不希望序列化那么多,可以使用这个接口,这个接口的writeExternal()和readExternal()方法可以指定序列化哪些属性; 但是如果你只想隐藏一个属性,比如用户对象user的密码pwd,如果使用Externalizable,并除了pwd之外的每个属性都写在writeExternal()方法里,这样显得麻烦,可以使用Serializable接口,并在要隐藏的属性pwd前面加上transient就可以实现了。
序列化的过程,是将任何实现了Serializable接口或 Externalizable接口的对象通过ObjectOutputStream类 提供的相应 方法转换为连续的字节数据,这些数据以后仍可通过 ObjectInputStream类 提供的相应方法被还原为原来的对象状态, 这样就可以将对象完成的保存在本地文件中,或在网络和进程间传递
实现Serializable接口的Demo
写一个student类实现Serializable接口
package com.neuedu.chapter03._文件与流_序列化;
import java.io.Serializable;
public class Student implements Serializable {
private String name; //私有属性
private int age;
/**
*
*/
public Student() {
super();//默认构造函数
// TODO Auto-generated constructor stub
}
/**
* @param name
* @param age
* 给name、age赋值的构造函数
*/
public Student(String name, int age) { //有参构造函数
super();
this.name = name;
this.age = age;
}
public String getName() { //成员变量的get和set方法
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
写一个实现序列化和反序列化的类(ObjectInputStream_ObjectOuputStream_Implements_Serializable)
package com.neuedu.chapter03._文件与流_序列化;
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 ObjectInputStream_ObjectOuputStream_Implements_Serializable {
//序列化方法
public static void serializanle() {
ObjectOutputStream output = null;
try {
//实例化student类
Student stu = new Student("大刘",19);
//实例化存放字节码的对象
FileOutputStream out = new FileOutputStream("file/student.txt");
//实例化序列化对象
output = new ObjectOutputStream(out);
//进行序列化
output.writeObject(stu);
//强制刷新
output.flush();
System.out.println("序列化对象成功!");
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally {
try {
if(output != null) {
output.close();
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
//反序列化方法
public static void deSerializable() {
ObjectInputStream input = null;
try {
//实例化对象,取到序列化对象的字节码存放文件
FileInputStream in = new FileInputStream("file/student.txt");
//创建反实例化对象
input = new ObjectInputStream(in);
//反序列化为Student对象
Student stu = (Student)input.readObject();
//打印反序列化出来的对象
System.out.println("反序列化出来的信息: "+stu.toString());
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public static void main(String[] args) {
serializanle();//序列化
deSerializable(); //反序列化
}
}
实现Externalizable接口的Demo
写一个类实现Externalizable接口
package com.neuedu.chapter03._文件与流_序列化;
import java.io.Externalizable;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectOutput;
public class Student_E implements Externalizable{
private int cno; //学号
private String cname;
private int psd; //学号密码
public Student_E() {
psd = 123456; //g给学设个密码赋值
}
/**
* @param cno
* @param cname
*/
public Student_E(int cno, String cname) { //无密码参数的构造函数
super();
this.cno = cno;
this.cname = cname;
}
public int getCno() {
return cno;
}
public void setCno(int cno) {
this.cno = cno;
}
public String getCname() {
return cname;
}
public void setCname(String cname) {
this.cname = cname;
}
public int getPsd() {
return psd;
}
public void setPsd(int psd) {
this.psd = psd;
}
//必须覆盖(重写)父类的序列化和反序列化的两个方法
@Override
public void writeExternal(ObjectOutput out) throws IOException {
// TODO Auto-generated method stub
//指定序列化时写入的属性,这不写学号的密码
out.writeObject(cno);
out.writeObject(cname);
}
@Override
public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
// TODO Auto-generated method stub
cno = (int)in.readObject();
cname = (String)in.readObject();
}
}
写一个类实现序列化和反序列化的类
package com.neuedu.chapter03._文件与流_序列化;
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 ObjectInputStream_ObjectOuputStream_Implements_Externalizable {
public static void externalizable() {
ObjectOutputStream output = null;
try {
//实例化student类
Student_E stu = new Student_E(1908,"小刘");
//实例化存放字节码的对象
FileOutputStream out = new FileOutputStream("file/student.txt");
output = new ObjectOutputStream(out);
//进行序列化
output.writeObject(stu);
//强制刷新
output.flush();
System.out.println("序列化对象成功!");
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
//反序列化
public static void deSerializable() {
ObjectInputStream input = null;
try {
//实例化对象,取到序列化对象的字节码存放文件
FileInputStream in = new FileInputStream("file/student.txt");
//创建反实例化对象
input = new ObjectInputStream(in);
//反序列化为Student对象
Student_E stu = (Student_E)input.readObject();
//打印反序列化出来的对象
System.out.println("反序列化出来的信息: "+stu.toString());
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public static void main(String[] args) {
externalizable();
deSerializable();
}
}