1、序列化简介
对象序列化是将对象状态转化为可保持或传输的格式的过程,一般而言对象序列化有以下作用:
- RMI(远程方法调用机制),网络传输,通过各个Socket作为对象之间的通信,从而实现程序组件在不同操作系统之间的通信,RMI大大增加了Java开发分布式应用的能力
- 将对象转化成文件,可保存到硬盘上,将对象储存起来,以便将来继续使用该对象
- 通过序列化在进程之间传递对象
序列化一个对象需要让他实现Serializable接口,Serializable接口是一个标记接口,不需要实现任何方法,Serializable接口的定义如下:
public interface Serializable {
}
Java对象被序列化时参与序列化的内容如下:
- 属性:如基本数据类型、数组和其他对象的引用
- 类名
不能被序列化的内容有:
- 方法,类中的所有方法
- static关键字和transient 关键字修饰的属性(transient 当前属性的数据不参与序列化和反序列化)
2、对象输出流:ObjectOutputStream
java.io.ObjectOutputStream类用于对象的序列化,即将一个对象输出,它实现了OutputStream接口,它的定义为:
public class ObjectOutputStream extends OutputStream implements ObjectOutput,ObjectStreamConstants
常用方法为:
3、对象输入流:ObjectInputStream
ObjectInputStream类用于对对象进行反序列化操作,ObjectInputStream类的定义如下:
public class ObjectInputStream extends InputStream implements ObjectInput,ObjectStreamConstants
实例:
/**
* 定义一个可序列化的类Student
* @author lzq
*
*/
public class Student implements Serializable {
private String name;
private int age;
private String school;
public Student() {
}
public Student(String name,int age,String school) {
this.name = name;
this.age = age;
this.school = school;
}
public void tell() {
System.out.println("名字:"+name+"\n年龄:"+age+"\n学校:"+school);
}
}
/**
* 用Serializable接口
* 对象的序列化和反序列化
* @author lzq
*
*/
public class TestDemo11 {
public static void main(String[] args) {
File file = new File("D:\\lzq/ObjectStudent.txt");
serializable(file);
deserializable(file);
}
/**
* 对象序列化
* @param file
*/
public static void serializable(File file) {
Student stu1 = new Student("小强",21,"哈佛");
Student stu2 = new Student("小红",22,"剑桥");
try {
FileOutputStream fout = new FileOutputStream(file);
ObjectOutputStream oos = new ObjectOutputStream(fout);
oos.writeObject(stu1);
oos.writeObject(stu2);
oos.close();
fout.close();
}catch(Exception e) {
e.printStackTrace();
}
}
/**
* 对象反序列化
* @param file
*/
public static void deserializable(File file) {
try {
FileInputStream fis = new FileInputStream(file);
ObjectInputStream ois = new ObjectInputStream(fis);
Student stu1 = (Student)ois.readObject();
Student stu2 = (Student)ois.readObject();
ois.close();
fis.close();
stu1.tell();
stu2.tell();
}catch(IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
运行结果:
保存的是二进制文件:
名字:小强
年龄:21
学校:哈佛
名字:小红
年龄:22
学校:剑桥
4、Externalizable接口
Java序列化有两种实现方法,一种是在类定义的时候实现Serializable接口,另一种是实现Externalizable接口,被Serializable接口声明的对象的内容都将被序列化,而Externalizable接口声明的类的对象可以选择需要序列化的内容,Externalizable接口定义了readExternal()和writeExternal()方法,实现该接口必须实现这两种方法。
实现Externalizable接口:
public class Student implements Externalizable {
private String name;
private int age;
private String school;
public Student() {
}
public Student(String name,int age,String school) {
this.name = name;
this.age = age;
this.school = school;
}
public void tell() {
System.out.println("名字:"+name+"\n年龄:"+age+"\n学校:"+school);
}
public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
this.name = (String)in.readObject();
this.school = (String)in.readObject();
}
public void writeExternal(ObjectOutput out) throws IOException {
out.writeObject(this.name);
out.writeObject(this.school); //选择name、school两个被序列化
}
}
/**
* 用Externalizable接口
* 对象的序列化和反序列化
* @author lzq
*
*/
public class TestDemo12 {
public static void main(String[] args) {
File file = new File("D:\\lzq/Externalizable.txt");
serialize(file);
deserialize(file);
}
/**
* 对象的序列化
* @param file
*/
private static void serialize(File file) {
Student stu1 = new Student("小强",21,"哈佛");
Student stu2 = new Student("小红",22,"剑桥");
try {
FileOutputStream fout = new FileOutputStream(file);
ObjectOutputStream oos = new ObjectOutputStream(fout);
oos.writeObject(stu1);
oos.writeObject(stu2);
oos.close();
fout.close();
}catch(Exception e) {
e.printStackTrace();
}
}
private static void deserialize(File file) {
try {
FileInputStream fis = new FileInputStream(file);
ObjectInputStream ois = new ObjectInputStream(fis);
Student stu1 = (Student)ois.readObject();
Student stu2 = (Student)ois.readObject();
ois.close();
fis.close();
stu1.tell();
stu2.tell();
}catch(IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
运行结果:
名字:小强
年龄:21
学校:哈佛
名字:小红
年龄:22
学校:剑桥
使用transient关键字声明不需要序列化的属性:
public class Student implements Serializable {
private String name;
private transient int age; //使用transient声明age属性不需要被序列化
private String school;
public Student() {
}
public Student(String name,int age,String school) {
this.name = name;
this.age = age;
this.school = school;
}
public void tell() {
System.out.println("名字:"+name+"\n年龄:"+age+"\n学校:"+school);
}
}
/**
* 用Serializable接口
* 对象的序列化和反序列化
* @author lzq
*
*/
public class TestDemo11 {
public static void main(String[] args) {
File file = new File("D:\\lzq/ObjectStudent.txt");
serializable(file);
deserializable(file);
}
/**
* 对象序列化
* @param file
*/
public static void serializable(File file) {
Student stu1 = new Student("小强",21,"哈佛");
Student stu2 = new Student("小红",22,"剑桥");
try {
FileOutputStream fout = new FileOutputStream(file);
ObjectOutputStream oos = new ObjectOutputStream(fout);
oos.writeObject(stu1);
oos.writeObject(stu2);
oos.close();
fout.close();
}catch(Exception e) {
e.printStackTrace();
}
}
/**
* 对象反序列化
* @param file
*/
public static void deserializable(File file) {
try {
FileInputStream fis = new FileInputStream(file);
ObjectInputStream ois = new ObjectInputStream(fis);
Student stu1 = (Student)ois.readObject();
Student stu2 = (Student)ois.readObject();
ois.close();
fis.close();
stu1.tell();
stu2.tell();
}catch(IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
运行结果:
名字:小强
年龄:0
学校:哈佛
名字:小红
年龄:0
学校:剑桥
age属性为0,说明age属性没有被序列化保存下来