序列化-Serializable接口
1.概念
序列化-将对象转化成字节序列的过程。
反序列化-将字节序列恢复成对象的过程。
2.目的
Java平台允许我们在内存中创建可复用的Java对象,但只有当JVM(Java虚拟机)处于运行时,这些对象才可能存在,也就是这些对象的生命周期不会比JVM的生命周期更长。但在现实应用中,就可能要求在JVM停止运行之后能够保存指定的对象(持久化对象),并在将来重新读取被保存的对象。Java对象序列化就实现了该功能。
所以序列化机制会把内存中的Java对象转换成与平台无关的二进制流,从而永久地保存在磁盘上或是通过网络传输到另一个网络节点。
3.方法
a. 把内存中的对象存到硬盘中或数据库中
b.使用socket进行对象的网络传输
c.通过RMI传输对象
4.具体实例
Servlet中HttpSession对象:每次用户访问产生会话都会生成一个HttpSession对象。当大量用户同时访问时,产生大量HttpSession对象,消耗服务器内存资源。且只有在这些HttpSession超时后,服务器才能释放内存。
因此,服务器通常把那些暂时不活动但未超时的HttpSession采用序列化的方式存储到文件系统或数据库中。等到服务器要使用这些HttpSession时,再通过反序列化的方式加载入内存。这项技术称为Session的持久化。
5.serialVersionUID
如果serialVersionUID没有显式生成,系统就会自动生成一个。此时,如果在序列化后我们将该类作添加或减少一个字段等的操作,系统在反序列化时会重新生成一个serialVersionUID然后去和已经序列化的对象进行比较,就会报序列号版本不一致的错误。为了避免这种问题, 一般系统都会要求实现serialiable接口的类显式的生明一个serialVersionUID。
显式定义serialVersionUID的两种用途:
1、 希望类的不同版本对序列化兼容时,需要确保类的不同版本具有相同的serialVersionUID;
2、 不希望类的不同版本对序列化兼容时,需要确保类的不同版本具有不同的serialVersionUID。
6.transient关键字
transient修饰瞬态属性,表示该属性不会被序列化。
当对象A被序列化时,将依次序列化其各个属性。当某属性引用到另一个对象B时,该对象B也将被序列化。若对象B的某属性引用到对象C时,对象C也将被序列化。这就是递归序列化。
7.writeObject与readObject方法
a.public final void writeObject(Object obj) throws IOException
将指定的对象写入 ObjectOutputStream。对象的类、类的签名,以及类及其所有超类型的非瞬态和非静态字段的值都将被写入。可以使用 writeObject 和 readObject 方法重写类的默认序列化。由此对象引用的对象是以可变迁的方式写入的,这样,可以通过 ObjectInputStream 重新构造这些对象的完全等价的图形。
b. public final Object readObject() throws IOException, ClassNotFoundException
从 ObjectInputStream 读取对象。对象的类、类的签名和类及所有其超类型的非瞬态和非静态字段的值都将被读取。可以使用 writeObject 和 readObject 方法为类重写默认的反序列化。由此对象引用的对象是可传递读取的,这样 readObject 即可重新构造这些对象的完全等价的图形。
8.注意事项
a.对象的类名、属性都会被序列化;而方法、static属性、transient属性都不会被序列化.
b.要序列化的对象的引用属性也必须是可序列化的,否则该对象不可序列化,除非transient关键字修饰该属性.
c.反序列化地象时必须有序列化对象生成的class文件(很多没有被序列化的数据需要从class文件获取)
d.当通过文件、网络来读取序列化后的对象时,必须按实际的写入顺序读取。
e.反序列化机制无需通过构造器来初始Java对象。
9.测试代码
public class SerializableTest {
public static void main(String[] args) throws FileNotFoundException, IOException, ClassNotFoundException {
Tin persi=new Tin("persi","blue","百事",1);
Tin coke=new Tin("coke","red","可口",2);
BigTin rio=new BigTin("rio","yellow","锐欧",1,200,350);
BigTin rioK=new BigTin("rio","orange","锐欧",2,250,350);
rio.setTin(persi);
rioK.setTin(coke);
System.out.println(rio);
System.out.println(rioK);
//序列化
ObjectOutputStream oos=new ObjectOutputStream(new FileOutputStream(new File("E:/serial.txt")));
oos.writeObject(rio);
//oos.writeObject(rioK); 注意可以写入多个对象,但需要按顺序读取;否则会导致数据读取失败;
oos.writeInt(66);
oos.close();
System.out.println("serial successfully");
//反序列化
ObjectInputStream ois=new ObjectInputStream(new FileInputStream(new File("E:/serial.txt")));
BigTin rio2=(BigTin)ois.readObject();
int out=ois.readInt();
ois.close();
System.out.println(rio==rio2);
System.out.println(rio.equals(rio2));
System.out.println("deserial successfully");
System.out.println(out);
System.out.println(rio2);
}
}
class BigTin extends Tin{
/**
*
*/
private static final long serialVersionUID = 263190832386845089L;
public BigTin(String name, String color, String brand, int num,int height,int weight) {
super(name, color, brand, num);
// TODO Auto-generated constructor stub
this.weight=weight;
BigTin.height=height;
}
@Override
public String toString() {
return "BigTin [tin=" + tin + ", height=" + height + ", weight=" + weight + ", name=" + name + ", color="
+ color + ", brand=" + brand + ", num=" + num + "]";
}
Tin tin;
static int height;
transient int weight;
public Tin getTin() {
return tin;
}
public void setTin(Tin tin) {
this.tin = tin;
}
}
class Tin implements Serializable{
/**
*
*/
private static final long serialVersionUID = 2947592207173916450L;
String name;
String color;
String brand;
transient int num;
public Tin(String name, String color, String brand, int num) {
super();
this.name = name;
this.color = color;
this.brand = brand;
this.num = num;
}
@Override
public String toString() {
return "Tin [name=" + name + ", color=" + color + ", brand=" + brand + ", num=" + num + "]";
}
}
结果:
BigTin [tin=Tin [name=persi, color=blue, brand=百事, num=1], height=250, weight=350, name=rio, color=yellow, brand=锐欧, num=1]
BigTin [tin=Tin [name=coke, color=red, brand=可口, num=2], height=250, weight=350, name=rio, color=orange, brand=锐欧, num=2]
serial successfully
false
false
deserial successfully
66
BigTin [tin=Tin [name=persi, color=blue, brand=百事, num=0], height=250, weight=0, name=rio, color=yellow, brand=锐欧, num=0]
Wed Apr 25 09:23:26 CST 2018
参考:https://bbs.csdn.net/topics/390155251/
https://blog.csdn.net/zcl_love_wx/article/details/52126876