序列化与反序列化
1.序列化基本概念
1.1对象序列化
对象序列化指的是,将内存中保存的对象变为二进制数据流的形式进行传输,或者将其保存在文本中(反序列化与序列化相反,实现对象持久化,即外部序列化)。但是并不是所有类的对象都可以被序列化,严格来说,需要被序列化的类的对象往往需要传输使用,同时这个类必须实现java.io.Serializable 接口 (Externalizable需要手动保存,很少用)),才具备对象序列化的功能。这个接口并莫有任何方法,它只是个标识而已。序列化对象时所需要保存的就是对象中的属性,所以默认情况下对象的属性将被转化为二进制数据流存在。
1.2对象序列化的特点
- 如果一个类能被序列化,那么它的子类也可以被序列化
- static代表的类成员,transient代表对象的临时数据,这两种数据成员是不能够被序列化的
2.对象序列化与对象反序列化
2.1序列化
在Java.io包中提供处理类:ObjectOutputStream(将对象转成二进制形式),ObjectOutput(不常用)
public class ObjectOutputStream extends OutputStream implements ObjectOutput, ObjectStreamConstants
public ObjectOutputStream(OutputStream out)throws IoException
WriteObject(Object obj)//将obj变为二进制流输出到目标终端
2.2反序列化
在Java.io包中提供处理类:ObjectInputStream(将二进制转化为对象),ObjectInput(不常用)
public class ObjectInputStream extends InputStream implements ObjectInput, ObjectStreamConstants
public ObjectInputStream(InputStream in) throws IoException
readObject() 选择反序列化的目标终端
2.3序列化与反序列化示例
class Person implements Serializable{
private transient String name;
private int age;
public Person(String name, int age) {
super();
this.name = name;
this.age = age;
}
@Override
public String toString(){
return "person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
public class TestSerializable {
public static void main(String[] args) throws IOException, ClassNotFoundException {
//序列化
Person per=new Person("马云",35);
OutputStream outputStream=new FileOutputStream(new File(
"C:\\Users\\QLH\\Desktop\\aaa.txt"));
ObjectOutputStream out= new ObjectOutputStream(outputStream);
out.writeObject(per);
outputStream.close();
out.close();
//反序列化
InputStream inputStream=new FileInputStream(new File(
"C:\\Users\\QLH\\Desktop\\aaa.txt"));
ObjectInputStream in=new ObjectInputStream(inputStream);
Person person=(Person) in.readObject();
System.out.println(person );
}
}
2.3.序列化的使用场景
由于序列化的使用会影响系统的性能,因此如果不是必须使用序列化,应尽可能的不要使用序列化,序列化的使用场景如下:
- 需要通过网络发送对象,或该对象的状态需要被持久化到数据库或文件中
- 序列化能实现深复制,即可复制引用的对象(深浅拷贝)
2.4反序列化与序列化主要区别
序列化是内置API,只需要实现serializable接口,开发人员不需要编写任何代码就可以实现对象的序列化,反序列化使用时,Externalizable接口中的读写方法必须由开发人员来实现。因此与实现serializable接口的方法相比,使用Externalizable编写程序的难度更大 ,但是在编程时把控制权交给开发后,使得编程更灵活,对需要持久化的那些属性可以进行控制,性能会提高。
3.部分属性序列化
3.1在接口中使用Serializable
在用接口Serializable接口时,若希望类中的若干属性不被序列化保存(serializable默认会将所有属性序列化保存),可以在属性前添加Transient关键字。transient关键字的作用:阻止实例中那些用此关键字修饰的变量序列化。当对象被反序列化时,被transient修饰的变量值不会被持久化和恢复。transient只能修饰变量,不能修饰类和方法。
3.2使用Externalizable
开发人员可根据实现需求来实现readExternal与writeExternal方法来控制序列化与反序列化所使用的的属性,这种方法的缺点是增加了编程的难度。