定义
对象序列化,就是将Object转换成byte序列,反之叫对象的反序列化.
- 序列化流(
ObjectOutputStream
),是过滤流----writeObject - 反序列化流(
ObjectInputStream
)----readObject
序列化接口(Serializable)
对象必须实现序列化接口 ,才能进行序列化,否则将出现异常
这个接口,没有任何方法,只是一个标准.
String file = "demo/obj.dat";
//1.对象的序列化
ObjectOutputStream oos = new ObjectOutputStream(
new FileOutputStream(file));
Student stu = new Student("10001", "张三", 20);
oos.writeObject(stu);
oos.flush();
oos.close();
//2.对象的反序列化
ObjectInputStream ois = new ObjectInputStream(
new FileInputStream(file));
Student stu = (Student)ois.readObject();
System.out.println(stu);
ois.close();
transient关键字
transient
修饰的变量不会进行jvm默认的序列化,但可以自己完成这个元素的序列化.即覆写:
private void writeObject(java.io.ObjectOutputStream s)
throws java.io.IOException
private void readObject(java.io.ObjectInputStream s)
throws java.io.IOException, ClassNotFoundException
public class Student implements Serializable{
private String stuno;
private String stuname;
//该元素不会进行jvm默认的序列化,也可以自己完成这个元素的序列化
private transient int stuage;
public Student(String stuno, String stuname, int stuage) {
super();
this.stuno = stuno;
this.stuname = stuname;
this.stuage = stuage;
}
public String getStuno() {
return stuno;
}
public void setStuno(String stuno) {
this.stuno = stuno;
}
public String getStuname() {
return stuname;
}
public void setStuname(String stuname) {
this.stuname = stuname;
}
public int getStuage() {
return stuage;
}
public void setStuage(int stuage) {
this.stuage = stuage;
}
@Override
public String toString() {
return "Student [stuno=" + stuno + ", stuname=" + stuname + ", stuage="
+ stuage + "]";
}
private void writeObject(java.io.ObjectOutputStream s)
throws java.io.IOException{
s.defaultWriteObject();//把jvm能默认序列化的元素进行序列化操作
s.writeInt(stuage);//自己完成stuage的序列化
}
private void readObject(java.io.ObjectInputStream s)
throws java.io.IOException, ClassNotFoundException{
s.defaultReadObject();//把jvm能默认反序列化的元素进行反序列化操作
this.stuage = s.readInt();//自己完成stuage的反序列化操作
}
}
如ArrayList
源码中对elementData
数组序列化和反序列化的处理,因为elementData
数组中不是所有元素都是有效元素,所以只序列化了size
个有效元素.
序列化中 子父类构造函数的调用问题
一个类实现了序列化接口,那么其子类都可以进行序列化.
对子类对象进行反序列化操作时,如果其父类没有实现序列化接口,那么其父类的构造函数会被调用.
public class ObjectSeriaDemo2 {
public static void main(String[] args) throws Exception{
//序列化Foo2
ObjectOutputStream oos = new ObjectOutputStream(
new FileOutputStream("demo/obj1.dat"));
Foo2 foo2 = new Foo2();
oos.writeObject(foo2);
oos.flush();
oos.close();
//反序列化Foo2是否递归调用父类的构造函数?不会调用Foo1(),Foo()
ObjectInputStream ois = new ObjectInputStream(
new FileInputStream("demo/obj1.dat"));
Foo2 foo2 = (Foo2)ois.readObject();
System.out.println(foo2);
ois.close();
//序列化Bar2
ObjectOutputStream oos = new ObjectOutputStream(
new FileOutputStream("demo/obj1.dat"));
Bar2 bar2 = new Bar2();
oos.writeObject(bar2);
oos.flush();
oos.close();
//反序列化Bar2是否递归调用父类的构造函数?会调用Bar1(),Bar()
ObjectInputStream ois = new ObjectInputStream(
new FileInputStream("demo/obj1.dat"));
Bar2 bar2 = (Bar2)ois.readObject();
System.out.println(bar2);
ois.close();
/*
* 对子类对象进行反序列化操作时,
* 如果其父类没有实现序列化接口
* 那么其父类的构造函数会被调用
*/
}
}
/*
* 一个类实现了序列化接口,那么其子类都可以进行序列化
*/
class Foo implements Serializable{
public Foo(){
System.out.println("foo...");
}
}
class Foo1 extends Foo{
public Foo1(){
System.out.println("foo1...");
}
}
class Foo2 extends Foo1{
public Foo2(){
System.out.println("foo2...");
}
}
class Bar{
public Bar(){
System.out.println("bar");
}
}
class Bar1 extends Bar{
public Bar1(){
System.out.println("bar1..");
}
}
class Bar2 extends Bar1 implements Serializable{
public Bar2(){
System.out.println("bar2...");
}
}