序列版本ID、序列方式深拷贝(包含JDK的序列化、反序列化)、序列化选型

序列版本ID:
    序列化时会写入序列版本ID,读时对比序列版本ID是否相同,不同则导致InvalidClassException。
    如果不写序列版本ID,JVM会自动生成,但不同JVM,应用的算法可能不同,可能导致序列版本ID不同,导致无法反序列化,建议写。
    IDEA可自动生成,Ctrl+Alt+S,然后搜索Serializable class without 'serialVersionUID'并勾选,在序列化类那里Alt+Enter,点击Add 'serialVersionUID' field。

 序列方式深拷贝:

import java.io.*;

/**
 * 类成员变量中基本数据类型和String类型会默认拷贝,这些类型之外的类型默认不拷贝,共用引用。如果这些类型之外的类型也拷贝了,就是深拷贝。
 */
public class DeepCloneBySerialization {
    public static void main(String[] args) throws Exception {
        Teacher teacher = new Teacher();
        teacher.setAge(50);
        teacher.setName("Teacher_甲");
        Student student1 = new Student();
        student1.setAge(23);
        student1.setName("Student_甲");
        student1.setTeacher(teacher);
        Teacher[] teacherArray = {teacher};
        student1.setTeacherArray(teacherArray);
        Student student2 = student1.deepClone();
        System.out.println(student2.getAge());
        System.out.println(student2.getName());
        System.out.println(student2.getTeacher().getAge());
        System.out.println(student2.getTeacher().getName());
        System.out.println(student2.getTeacherArray()[0].getName());
        System.out.println("-----------------------");
        student2.getTeacher().setAge(77);
        student2.getTeacher().setName("Teacher_乙");
        System.out.println(teacher.getAge());
        System.out.println(teacher.getName());
        System.out.println(student2.getTeacher().getAge());
        System.out.println(student2.getTeacher().getName());
        System.out.println(student2.getTeacherArray()[0].getName());
    }
}

class Teacher implements Serializable {
    private static final long serialVersionUID = -7383978843190364934L;
    private int age;
    private String name;

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

class Student implements Serializable {
    private static final long serialVersionUID = 5913268735291548932L;
    private int age;
    private String name;
    private Teacher teacher;
    private Teacher[] teacherArray = new Teacher[1];

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Teacher getTeacher() {
        return teacher;
    }

    public void setTeacher(Teacher teacher) {
        this.teacher = teacher;
    }

    public Teacher[] getTeacherArray() {
        return teacherArray;
    }

    public void setTeacherArray(Teacher[] teacherArray) {
        this.teacherArray = teacherArray;
    }

    public Student deepClone() throws Exception {
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        ObjectOutputStream oos = new ObjectOutputStream(bos);
        oos.writeObject(this);
        ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
        ObjectInputStream ois = new ObjectInputStream(bis);
        return (Student)ois.readObject();
    }
}

转: 

序列化考虑的因素:
(1)序列化的数据大小(影响传输效率)
(2)是否跨语言 
举例:
hassian
Hessian 是一个支持跨语言传输的二进制序列化协议,相对于 Java 默认的序列化机制来说,
Hessian 具有更好的性能和易用性,而且支持多种不同的语言实际上 Dubbo 采用的就是 Hessian 序列化来实现,只不过 Dubbo 对 Hessian 进行了重构,称 hassian2,
性能更高 。
msgpack
protobuf (压缩率非常高):
Protocol Buffer 的性能好,主要体现在 序列化后的数据体积小 & 序列化速度快,最终使得
传输效率高,其原因如下:
序列化速度快的原因:
a. 编码 / 解码 方式简单(只需要简单的数学运算 = 位移等等)
b. 采用 Protocol Buffer 自身的框架代码 和 编译器 共同完成
序列化后的数据量体积小(即数据压缩效果好)的原因:
a. 采用了独特的编码方式,如 Varint、Zigzag 编码方式等等
b. 采用 T - L - V 的数据存储方式:减少了分隔符的使用 & 数据存储得紧凑
kyro:
Kryo 是一种非常成熟的序列化实现,已经在 Hive、Storm)中使用得比较广泛,不过它不能
跨语言. 目前 dubbo 已经在 2.6 版本支持 kyro 的序列化机制。它的性能要优于之前的
hessian2
avro:
Avro 是一个数据序列化系统,设计用于支持大批量数据交换的应用。它的主要特点有:支持
二进制序列化方式,可以便捷,快速地处理大量数据;动态语言友好,Avro 提供的机制使动
态语言可以方便地处理 Avro 数据。
json(跨语言特性、序列化效率高 ):
JSON(JavaScript Object Notation)是一种轻量级的数据交换格式,相对于 XML 来说,JSON
的字节流更小,而且可读性也非常好。现在 JSON 数据格式在企业运用是最普遍的
JSON 序列化常用的开源工具有很多
1. Jackson ( https://github.com/FasterXML/jackson
2. 阿里开源的 FastJson ( https://github.com/alibaba/fastjon
3. Google 的 GSON (https://github.com/google/gson)
这几种 json 序列化工具中,Jackson 与 fastjson 要比 GSON 的性能要好,但是 Jackson、
GSON 的稳定性要比 Fastjson 好。而 fastjson 的优势在于提供的 api 非常容易使用
jute(zookeeper)
技术层面
1. 序列化空间开销,也就是序列化产生的结果大小,这个影响到传输的性能
2. 序列化过程中消耗的时长,序列化消耗时间过长影响到业务的响应时间
3. 序列化协议是否支持跨平台,跨语言。因为现在的架构更加灵活,如果存在异构系统通信
需求,那么这个是必须要考虑的
4. 可扩展性/兼容性,在实际业务开发中,系统往往需要随着需求的快速迭代来实现快速更新,
这就要求我们采用的序列化协议基于良好的可扩展性/兼容性,比如在现有的序列化数据结
构中新增一个业务字段,不会影响到现有的服务
5. 技术的流行程度,越流行的技术意味着使用的公司多,那么很多坑都已经淌过并且得到了 解决,技术解决方案也相对成熟
6. 学习难度和易用性
选型建议
1. 对性能要求不高的场景,可以采用基于 XML 的 SOAP 协议
2. 对性能和间接性有比较高要求的场景,那么 Hessian、Protobuf、Thrift、Avro 都可以。
3. 基于前后端分离,或者独立的对外的 api 服务,选用 JSON 是比较好的,对于调试、可读
性都很不错
4. Avro 设计理念偏于动态类型语言,那么这类的场景使用 Avro 是可以的
各个序列化技术的性能比较
这个地址有针对不同序列化技术进行性能比较: https://github.com/eishay/jvm-serializers/wiki

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

风铃峰顶

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值