概念
序列化:将对象保存到磁盘中,或允许在网络中直接传输对象,对象序列化机制允许把内存中的Java对象转换成平台无关的二进制,从而可以持久的保存在磁盘上,也可以在网络中传输。
反序列化:程序一旦获得了序列化的对象,则这种二进制流都可以恢复成原来的
如何实现序列化
1.Serializable
要序列化的对象,实现该接口,无需重写任何方法
2.Externalizable
要序列化的对象实现该接口,并且需要实现writeExternal和readExternal方法
简单对象的序列化
1.单一的对象序列化
创建一个Person类
public class Person implements Serializable{
private String id;
public Person(String id) {
System.out.println("youcacn");
this.id = id;
}
@Override
public String toString() {
return "Person{" +
"id='" + id + '\'' +
'}';
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
}
注意:1.Person类实现了Serializable接口
2.该实体类没有提供无参构造函数
写一个测试类,测试一下序列化与反序列化
try {
//序列化
ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream("2.txt"));
Person person = new Person("111");
objectOutputStream.writeObject(person);
//反序列化
ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream("2.txt"));
Person person1 = (Person) objectInputStream.readObject();
System.out.println(person1.toString());
} catch (Exception e) {
e.printStackTrace();
}
执行结果
Person类去掉实现序列化接口(即,将public class Person implements Serializable修改为public class Person),重新执行
结论:简单类型(无继承关系)对象序列化时必须实现序列化接口,有无无参构造函数都key
2.存在继承关系,但并无引用关系的对象序列化
创建Student类,继承Person类
public class Student extends Person implements Serializable{
private int no;
@Override
public String toString() {
return "Student{" +
"no=" + no +
'}';
}
public Student(String id ,int no) {
super(id);
this.no = no;
}
public int getNo() {
return no;
}
public void setNo(int no) {
this.no = no;
}
}
Person类对象既没实现序列化接口,又没有提供无参构造函数
public class Person{
private String id;
// public Person() {
// }
public Person(String id) {
System.out.println("youcacn");
this.id = id;
}
@Override
public String toString() {
return "Person{" +
"id='" + id + '\'' +
'}';
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
}
执行序列化与反序列化
另Person对象实现序列化接口,再次执行,结果成功
public class Person implements Serializable{
private String id;
// public Person() {
// }
public Person(String id) {
System.out.println("youcacn");
this.id = id;
}
@Override
public String toString() {
return "Person{" +
"id='" + id + '\'' +
'}';
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
}
不实现序列化接口,提供无参构造函数,执行结果成功
public class Person {
private String id;
public Person() {
}
public Person(String id) {
System.out.println("youcacn");
this.id = id;
}
@Override
public String toString() {
return "Person{" +
"id='" + id + '\'' +
'}';
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
}
结论:存在继承关系时,若想序列化子类对象,一并序列化父类对象,则负责类型必须实现序列化接口或者提供无参构造函数
对象引用的序列化
Student类继承Person类,并有对象引用关系
public class Student extends Person implements Serializable {
private int no;
private Person person;
public Person getPerson() {
return person;
}
public void setPerson(Person person) {
this.person = person;
}
@Override
public String toString() {
return "Student{" +
"no=" + no +
'}';
}
public Student(String id, int no) {
super(id);
this.no = no;
}
public int getNo() {
return no;
}
public void setNo(int no) {
this.no = no;
}
}
一个demo序列化Student实例与反序列化Student实例
try {
//序列化
ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream("2.txt"));
Person person = new Person("111");
Student stuB = new Student("B", 163);
stuB.setPerson(person);
objectOutputStream.writeObject(stuB);
//反序列化
ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream("2.txt"));
Student student = (Student) objectInputStream.readObject();
System.out.println(student.getPerson());
} catch (Exception e) {
e.printStackTrace();
}
Person类不实现序列化接口,也不提供无参构造函数,执行结果如下:
Person类不实现序列化接口,提供无参构造函数,执行结果如下:
Person类实现序列化接口,但不提供无参构造函数,执行结果如下:
结论
单一对象,无继承关系:若想实现序列化与反序列化,则必须实现序列化接口,否则报异常:NotSerializableException
对象间有继承关系,但无引用关系,若想实现序列化与反序列化,则父类必须实现序列化接口或提供无参构造函数,否则报invalidClassException
对象间有继承关系,并且有引用关系,若想实现序列化与反序列化,则父类必须实现序列化接口