在最近写的小程序里,使用到了序列化 Serializable,对序列化不是很熟悉,于是写个博客记录一下序列化
序列化Serializable一般有两个作用
1.把对象转换为字节序列输出到硬盘上,得到长期保存,还能减少内存的消耗
2.当对象需要在网络上进行传输时,就需要进行序列化,以便能在网络以字节传输
反序列化
把字节序列转换成对象的过程叫做反序列化,如在网络连接中,接收方把字节序列恢复成对象,从硬盘读出字节序列在转换成对象
实现序列化
要想实现序列化,类必须实现Serializable接口,该接口没有任何方法,只是一个规定,实现序列化就必须要有这个接口,如没有实现这个接口就会抛出NotSerializableException异常,并标识不可被序列化对象的类
/*实现Serializable接口*/
public class Students implements Serializable {
private int stuNum;
private String name;
public Students(int stuNum, String name) {
this.stuNum = stuNum;
this.name = name;
}
public int getStuNum() {
return stuNum;
}
public String getName() {
return name;
}
@Override
public String toString() {
return "Students{" +
"stuNum=" + stuNum +
", name='" + name + '\'' +
'}';
}
}
ObjectOutputStream代表对象输出流,它的writeObject(Object obj)方法可对参数指定的obj对象进行序列化,把得到的字节序列写到一个目标输出流中。
ObjectInputStream代表对象输入流,它的readObject()方法从一个源输入流中读取字节序列,再把它们反序列化为一个对象,并将其返回。
序列化步骤
1.创建对象输出流对象,可以嵌套多种其他输出流,如FileOutputStream
2.使用writeObject(Object obj)方法序列化指定对象
反序列化步骤
1.创建对象输入流对象,可以嵌套多种其他输入流,如FileInoutStrem
2.使用readObject()方法读出对象,进行反序列化
public class SerializableDemo {
public static void main(String[] args)throws Exception {
String fileName="D:\\File\\kang\\788.txt";
Students stu=new Students(10010, "张三");
ObjectOutputStream op=new ObjectOutputStream(new FileOutputStream(fileName));//嵌套文件输出流
op.writeObject(stu);
op.flush();
op.close();
ObjectInputStream obi=new ObjectInputStream(new FileInputStream(fileName));//嵌套文件输入流
Students stuu=(Students) obi.readObject();
obi.close();
System.out.println(stuu);
}
}
Serializable接口采用默认的序列化方式,只有在写出对象时才能用writeObject/readObject方法,对于基本类型需要使用诸如writeInt/readInt,writeDouble/readDouble等方法,对象流都实现了DataInput/DataOutput接口
transient
当希望一些变量不被序列化时,如一些只对本地方法有意义的存储文件句柄或窗口句柄的整数值,可以使用transient关键字,transient的作用是使被该关键字修饰的变量不会被序列化,当然也不会被反序列化
上面序列化的和反序列化的结果
name变量加上transient关键字后
没被序列化的变量,在反序列化后读出的是默认值,String的默认值是null