Java对象序列化和反序列化:进程之间通信将JAVA对象和目标二进制文件进行转换,用于网络通信之间的数据传输,也是数据持久化的一种方式
- 序列化:JAVA对象转换为二进制字节序列的过程
- 反序列化:二进制字节序列解析为JAVA对象的过程
- 对象可序列化的条件:实现Serializable接口序列化
应用:java框架中定义的对象80%都是序列化对象,作用为了更方便进行数据传输
package com.zhiwei.basic;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
public class ObjectSerializable {
public static void main(String[] args) throws Exception{
//String类实现了Serializable接口
String str=new String("abcsdcsdcdscsdcsdcssd");
System.out.println("序列化对象String:"+str);
FileOutputStream fos=new FileOutputStream("d:/temp.txt");
ObjectOutputStream oos=new ObjectOutputStream(fos);
oos.writeObject(str);
FileInputStream fis=new FileInputStream("d:/temp.txt");
ObjectInputStream ois=new ObjectInputStream(fis);
Object strCopy=ois.readObject();
System.out.println("反序列化对象String:"+strCopy);
System.out.println("\n");
//注意反序列化之后的对象和原对象的对象16进制表示格式不一样,类似拷贝的原理
AAAAAA aa=new AAAAAA("AAAA","BBBBB");
System.out.println("序列化对象:"+aa);
System.out.println("序列化前:"+aa.getAa());
fos=new FileOutputStream("d:/temp.txt");
oos=new ObjectOutputStream(fos);
oos.writeObject(aa);
fis=new FileInputStream("d:/temp.txt");
ois=new ObjectInputStream(fis);
AAAAAA bb=(AAAAAA) ois.readObject();
System.out.println("反序列化对象:"+bb);
System.out.println("序列化后:"+bb.getAa());
ois.close();
oos.close();
}
}
class AAAAAA implements Serializable{ //简单可实例化的POJO对象
//序列号:作用校验序列化原对象和反序列化之后的对象是否一致:JVM检测
private static final long serialVersionUID = 1L;
private String aa;
private String bb;
public String getAa() {
return aa;
}
public void setAa(String aa) {
this.aa = aa;
}
public String getBb() {
return bb;
}
public void setBb(String bb) {
this.bb = bb;
}
public AAAAAA(String aa, String bb) {
super();
this.aa = aa;
this.bb = bb;
}
}
结果显示:
序列化对象String:abcsdcsdcdscsdcsdcssd
反序列化对象String:abcsdcsdcdscsdcsdcssd
序列化对象:com.zhiwei.basic.AAAAAA@6ce253f1
序列化前:AAAA
反序列化对象:com.zhiwei.basic.AAAAAA@4c873330
序列化后:AAAA
结论:
序列化只是对对象实例的拷贝,使得对象实例可以以文件或者其他的形式持久化存储,如果不需要文件进行持久化存储介质,可以使用ByteArrayInputStream/ByteArrayOutputStream将序列化数据存放在缓存字节数据中,缓存充当临时存储介质
主要代码:
String str=new String("abcsdcsdcdscsdcsdcssd");
ByteArrayOutputStream bos=new ByteArrayOutputStream();
ObjectOutputStream oos=new ObjectOutputStream(bos);
oos.writeObject(str);
//bos.toByteArray():字节缓存数组缓存的数据
ByteArrayInputStream bis=
new ByteArrayInputStream(bos.toByteArray());
ObjectInputStream ois=new ObjectInputStream(bis);
Object object=ois.readObject();
System.out.println(object);
//包裹流关闭其基础流也会一起关闭
ois.close();
oos.close();
特别注意:serialVersionUID 必须指定版本号,否则可能出现版本号不一致的导致反序列化失败的情况
分析:serialVersionUID默认版本号生成与JDK相关,如果客户端和服务端JDK版本号一致,那么对相同对象解析的版本号一致,就不存在反序列化失败问题,如果客户端和服务端JDK版本号不一致,例如openjdk、oracle jdk等,导致2个版本号默认生成的版本号不一致,导致反序列化报错