Java序列化的实现方式有哪些?
前言
Java常用的序列化方式包括基于流序列化、Json序列化、FastJson序列化、ProtoBuf序列化....
PS:基于流序列化的对象必须实现Serializable、Externalizable,会自动序列化所有非static和transient关键字修饰的成员变量
4种序列化方式实例
公共实体类
public class Student implements Serializable {
@Protobuf(fieldType = FieldType.STRING, required = false, order = 1)
private String name;
@Protobuf(fieldType = FieldType.INT32, required = false, order = 2)
private int age;
@Protobuf(fieldType = FieldType.STRING, required = false, order = 3)
public static String QQ = "123456";
@Protobuf(fieldType = FieldType.STRING, required = false, order = 4)
public transient String address = "CHINA"; // 被transient标记的变量不会被序列化(基于流)
public Student() {
}
public Student(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "org.ccccye.study.serializable.Student{" +
"name='" + name + '\'' +
", age=" + age +
", QQ=" + QQ +
", address='" + address + '\'' +
'}';
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
实例代码
public class SerializableTest {
public static void main(String[] args) throws IOException, ClassNotFoundException {
Student student = new Student("john", 18);
System.out.println(student);
// 1. 基于流序列化
Long t1 = System.currentTimeMillis();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream out = new ObjectOutputStream(baos);
out.writeObject(student);
System.out.println("serialize "+(System.currentTimeMillis()-t1)+"ms, length:"+baos.toByteArray().length);
Long t2 = System.currentTimeMillis();
ObjectInputStream in = new ObjectInputStream(new ByteArrayInputStream(baos.toByteArray()));
Student newStudent = (Student) in.readObject();
System.out.println("deserialize:"+(System.currentTimeMillis()-t2)+"ms");
System.out.println("serialize--"+newStudent);
in.close();
out.close();
// 2. jackson序列化
ObjectMapper mapper = new ObjectMapper();
t1 = System.currentTimeMillis();
byte[] buff = mapper.writeValueAsBytes(student);
System.out.println("jackson serialize "+(System.currentTimeMillis()-t1)+"ms, length:"+buff.length);
// 反序列化
t2 = System.currentTimeMillis();
newStudent = mapper.readValue(buff, Student.class);
System.out.println("jackson deserialize "+(System.currentTimeMillis()-t2)+"ms");
System.out.println("jackson--"+newStudent);
// 3. fastjson序列化
t1 = System.currentTimeMillis();
buff = JSON.toJSONBytes(student);
System.out.println("fastjson serialize "+(System.currentTimeMillis()-t1)+"ms, length:"+buff.length);
t2 = System.currentTimeMillis();
newStudent = (Student) JSON.parseObject(buff,Student.class);
System.out.println("fastjson deserialize "+(System.currentTimeMillis()-t2)+"ms");
System.out.println("fastjson=="+newStudent);
// 4. protobuf序列化
Codec<Student> codec = ProtobufProxy.create(Student.class, false);
t1 = System.currentTimeMillis();
buff = codec.encode(student);
System.out.println("protobuf serialize "+(System.currentTimeMillis()-t1)+"ms, length:"+buff.length);
t2 = System.currentTimeMillis();
newStudent = codec.decode(buff);
System.out.println("protobuf deserialize "+(System.currentTimeMillis()-t2)+"ms");
System.out.println("protobuf--"+newStudent);
}
}
打印结果
org.ccccye.study.serializable.Student{name='john', age=18, QQ=123456, address='CHINA'}
serialize 87ms, length:103
deserialize:166ms
serialize--org.ccccye.study.serializable.Student{name='john', age=18, QQ=123456, address='null'}
jackson serialize 231ms, length:24
jackson deserialize 91ms
jackson--org.ccccye.study.serializable.Student{name='john', age=18, QQ=123456, address='CHINA'}
fastjson serialize 226ms, length:24
fastjson deserialize 40ms
fastjson==org.ccccye.study.serializable.Student{name='john', age=18, QQ=123456, address='CHINA'}
protobuf serialize 33ms, length:23
protobuf deserialize 0ms
protobuf--org.ccccye.study.serializable.Student{name='john', age=18, QQ=123456, address='CHINA'}
性能数据经过整理后
序列化方式 | 序列化耗时(ms) | 反序列化耗时(ms) | 数据大小 |
---|---|---|---|
Serialize | 87 | 166 | 103 |
jackson | 231 | 91 | 24 |
fastjson | 226 | 40 | 24 |
protobuf | 33 | 0 | 23 |
总结
经过测试,在数据量很少的情况下,jackson和fastjson的资源开销差不多;与json相比,原生流的反序列化和数据大小表现远远差于json,但是序列化耗时较少;最强的是protobuf在数据大小跟json一致的情况下,序列化/反序列化耗时远远低于json,甚至反序列化1个对象时耗时接近于0
参考文档
oldmee https://blog.csdn.net/javaer_lee/article/details/89098754