? 将内存中的对象,以字节码形式存储起来,等待用时反序列化回来,主要是IO操作,可以有更长的生命周期和跨项目性质的作用。
序列化
:将对象的信息转化为字节码的形式存储或传输的过程,称为序列化。
public class Person{
private String name;
public void setName(String name){
this.name = name
}
public String getName(){
return name;
}
}
Person person = new Person();
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(new File("person.txt")));
oos.writeObject(person);
? 反序列化
:序列化的逆向过程,将字节码读取转化为对象的过程,称为反序列化。
ObjectInputStream ois = new ObjectInputStream(new FileInputStream(new File("person.txt")));
Person person = (Person) ois.readObject();
序列化的实现方式优劣指标
:
Java序列化的缺点
:
JDK序列化中serialVersionUID的作用
:
Java的序列化机制是通过判断类的serialVersionUID来验证版本一致性的。在进行反序列化时,JVM 会把传来的字节流中的 serialVersionUID与本地相应实体类的 serialVersionUID 进行比较,如果相同就认为是一致的,可以进行反序列化,否则就会出现序列化版本不一致的异常,即是 InvalidCastException
如果没有为指定的 class 配置 serialVersionUID,那么 java 编译器会自动给这个 class 进行一个摘要算法,类似于指纹算法,只要这个文件有任何改动,得到的 UID 就会截然不同的,可以保证在这么多类中,这个编号是唯一的
serialVersionUID生成规则
静态变量序列化
? 序列化时并不保存静态变量,序列化保存的是对象的状态,静态变量属于类的状态,因此序列化并不保存静态变量。
父类序列化问题
? 子类实现了Serializable接口,父类未实现,在子类中调用父类属性赋值,序列化过程中出现的情况
Transient关键字
? 使用transient修饰的属性,java序列化时,会忽略掉此字段,所以反序列化出的对象,被transient修饰的属性是默认值。对于引用类型,值是null;基本类型,值是0;boolean类型,值是false,初始值。
重复序列化问题
? Java序列化同一对象,并不会将此对象序列化多次得到多个对象
? Java序列化算法:
可以作为深度克隆
? Java的拷贝一般都是实现Cloneable接口,并重写clone方法进行拷贝操作,主要是对象表皮复制了一份,内部属性的对象引用未改变。
属性类型是基本数据类型或者String字符串类型不影响。
? 针对拷贝时对象属性引用问题有几种解决方式
可以在对象属性字段的对象也加上实现Cloneable接口调用clone(比较麻烦),如下:
@Override
public Object clone() throws CloneNotSupportedException {
Teacher teacher = (Teacher) super.clone();
//把引用类型的变量在克隆一份
teacher.setStudent((Student) teacher.getStudent().clone());
return teacher;
}
可以利用序列化的方式,将对象转化为字节流,再转化回对象,做个中转(可能稍微有点麻烦,但非常实用),如下:
public Object copyObject(Object object) throws IOException, ClassNotFoundException {
//创建字节数组输出流将索要拷贝对象写入
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
//创建对象输出流将字节数组输出流传入直接将对象写入字节输出流
ObjectOutputStream objectOutputStrea = new ObjectOutputStream(byteArrayOutputStream);
objectOutputStrea.writeObject(object);
//将刚写入的输出流转化为字节数组传入字节数组输入流
ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(byteArrayOutputStream.toByteArray());
//对象输入流包装读取为一个对象
ObjectInputStream objectInputStream = new ObjectInputStream(byteArrayInputStream);
return objectInputStream.readObject();
}
还有可以使用JSON的方式,先将对象转为json,再转回对象,这是不错的想法
?
原文:https://www.cnblogs.com/zhouguanglin/p/14429031.html