Java的对象的序列化将那些实现了serializable接口的对象转换成一个字节序列,并能够在以后将这个字节序列恢复为原来的对象
(序列化能通过网络进行,弥补不同操作系统之间的差异)
简而言之:
对象序列化就是讲object转换成byte序列,反之叫对象的反序列化。
具体步骤:
序列化:
- 创建OutputStream对象
- 封装在一个ObjectOutputStream对象内。
- 调用writeObject()方法,并将其发送给OutputStream
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();
反序列化:
- 创建InputStream对象
- 封装在一个ObjectIntputStream对象内。
- 调用readObject()方法,并将其发送给InputStream
String file = "demo/obj.dat";
ObjectInputStream ois = new ObjectInputStream(
new FileInputStream(file));
Student stu = (Student)ois.readObject();
System.out.println(stu);
ois.close();
transient(顺时)关键字
当我们队序列化进行控制时,可能某个特定子对象不想让Java的序列化机制自动保存与恢复如果子对象表示的是我们不希望将其序列化的敏感信息(如密码),通常就会面临这种情况。及时对象中的这些信息是private属性,一经序列化处理,人们就可以通过读取文件或者拦截网络传输的方式得到它。
为了能够加以控制,可以用transient关键字逐个字段地关闭序列化他的意思是不用麻烦保存或者回复数据,我自己会处理好。
示例:
//该元素不会进行jvm默认的序列化,也可以自己完成这个元素的序列化 private transient int stuage;
可以自己进行序列化和反序列化:
实现了Serializable接口的对象,并添加(不是覆盖或者实现)writeObject()和readObject()(private)方法。如此,一旦对象被序列化和反序列化时,会自动调用这两个方法,而不是默认的反序列化机制。
此外:在两个方法内部可以分别调用defaultWriteObject()来执行默认的writeObject(),defaultReadObject()来执行默认的readObject()
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的反序列化操作
}
序列化中子类和父类构造函数的调用问题
结论一. 序列化会依次调用父类构造函数
测试对象:
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...");
}
测试代码
输出结果
测试一 结果一 测试二 结果二结论二. 对子类对象进行反序列化操作时, 如果其父类没有实现序列化接口, 那么其父类的构造函数会被调用*
测试代码:
网友评论