不同的序列化方法:
-
Java 序列化的优点是:对对象的结构描述清晰,反序列化更安全。主要缺点是:效率低,序列化后的二进制流较大。
-
Hession 序列化二进制流较 Java 序列化更小,且序列化和反序列化耗时更短。但是父类和子类有相同类型属性时,由于先序列化子类再序列化父类,因此反序列化时子类的同名属性会被父类的值覆盖掉,开发时要特别注意这种情况。
-
Kryo 优点是:速度快、序列化后二进制流体积小、反序列化超快。但是缺点是:跨语言支持复杂。注册模式序列化更快,但是编程更加复杂。
-
JSON 序列化的优势在于可读性更强。主要缺点是:没有携带类型信息,只有提供了准确的类型信息才能准确地进行反序列化,这点也特别容易引发线上问题。
一些笔记
1、反序列化不需要通过构造器
2、序列化只是读取对象的数据,不是类数据,
3、序列化的部分:实例变量,类名
不序列化的部分:方法,类变量,transient修饰的变量
4、对象的引用对象也会被递归序列化
5、序列化算法:
-
保存到磁盘的对象都有一个序列化编号
-
在序列化对象时,先检查该对象是否已经被序列化过,只有该对象从未序列化后才会转化成字节码输出
-
某个对象已经序列化过了,直接输出一个序列化编号,而不是再重新序列化该对象。
6、在序列化可变对象时,只有第一次序列化输出时会转为字节序列输出,后面即使对象变量改变了也不会重新序列化,只是输出一个序列化编号。
7、自定义序列化
@Data
public class PersonTransit implements Serializable {
private Long id;
private String name;
private Boolean male;
private List<PersonTransit> friends;
private Address address;
private void writeObject(ObjectOutputStream out) throws IOException{
String add= JSON.toJSONString(address);
out.writeObject(add);
out.writeLong(id);
out.writeObject(name);
out.writeBoolean(male);
out.writeObject(friends);
}
private void readObject(ObjectInputStream out) throws IOException, ClassNotFoundException {
String add=(String) out.readObject();
address=JSON.parseObject(add,Address.class);
id=out.readLong();
name=(String)out.readObject();
male=(Boolean) out.readBoolean();
friends=(List<PersonTransit>)out.readObject();
}
添加了自定义的writeObject()和readObject()方法,来处理没有实现序列化接口的Address对象。
@Test
public void testJDKSerial() throws IOException, ClassNotFoundException {
ObjectOutputStream outputStream=new ObjectOutputStream(new FileOutputStream("object.txt"));
outputStream.writeObject(personTransit);
ObjectInputStream objectInputStream=new ObjectInputStream(new FileInputStream("object.txt"));
PersonTransit personTransit2=(PersonTransit) objectInputStream.readObject();
System.out.println(personTransit2);
}
如果使用fastJson就不用进行处理
@Test
public void testFastJsonSerial() {
String person=JSON.toJSONString(personTransit);
PersonTransit personTransit1=JSON.parseObject(person,PersonTransit.class);
System.out.println(personTransit1);
}