序列化

序列化和反序列化

序列化:将Java对象转换为有序字节流的过程;转化过程保证对象的完整性和可传递性,转换完成后形成有序字节流,以便在网络上进行传输或保存到磁盘中;

反序列化:将有序字节流转化为Java对象的过程;根据有序字节流中保存的对象状态和信息,反序列化出对象。

序列化优点

  • 将对象序列化转换为字节流,存储到磁盘中;减少内存压力,也可以永久保存对象,等到下次JVM启动时在通过反序列化还原对象。
  • 方便在网络中进行传输
  • 通过序列化,将对象保存在内存中,可以再通过此数据得到多个对象的副本。

过程

  1. 只有实现了Serializable接口的类才能序列化
  2. 序列化和反序列化API:
    1. java.io.ObjectInputStream:对象输入流。该类的readObject()方法从输入流中读取字节序列,然后将字节序列反序列化为一个对象并返回。
    2. java.io.ObjectOutputStream:对象输出流。该类的writeObject(Object obj)方法将将传入的obj对象进行序列化,把得到的字节序列写入到目标输出流中进行输出。
public class TestSerialVersionUID {

    private static String pathName = "D:/Customer.txt";

    public static void main(String[] args) throws Exception {
        serializeCustomer();// 序列化Customer对象
        Customer customer = deserializeCustomer();// 反序列Customer对象
        System.out.println(customer);
    }

    private static void serializeCustomer() throws IOException {
        Customer customer = new Customer("gacl", 25);
        customer.setNum("static Num");
        // ObjectOutputStream 对象输出流
        try (ObjectOutputStream oo = new ObjectOutputStream(new FileOutputStream(
                new File(pathName)))) {
            oo.writeObject(customer);
            System.out.println("Customer对象序列化成功!");
        }
    }

    private static Customer deserializeCustomer() throws Exception {
        try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream(
                new File(pathName)))) {
            Customer customer = (Customer) ois.readObject();
            System.out.println("Customer对象反序列化成功!");
            return customer;
        }
    }

}

@Data
class Customer implements Serializable {

    private static final long serialVersionUID = -2812038111916495724L;
    //Customer类中没有定义serialVersionUID
    private String name;
    private int age;
    //新增
    private int sex;

    private static String num;

    public Customer(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public Customer(String name, int age, int sex) {
        this.name = name;
        this.age = age;
        this.sex = sex;
    }

    public static void setNum(String n){
        num = n;
    }

    public static String getNum(){
        return num;
    }

    @Override
    public String toString() {
        return "Customer{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", sex=" + sex +
                ", num=" + num +
                '}';
    }
}

在运行程序时,main方法分两次运行,两次执行分别注释掉序列化和反序列化方法,模拟在两个JVM下运行,运行结果:

//第一次运行结果
Customer对象序列化成功!

//第二次运行结果
Customer对象反序列化成功!
Customer{name='gacl', age=25, sex=0, num=null}

注意

  1. 父类实现序列化,子类自动实现序列化,不需要显示实现Serializable接口;
  2. 当一个属性为对象类型,序列化时也要对对象类型属性进行序列化,即该对象类型也要支持序列化;
  3. 声明为static和transient(例如:ArrayList中elementData)的不能被序列化,transient代表对象临时数据;
    1. 静态成员属于类级别(随着类的加载而加载的,与类共存亡),所以不能序列化,即序列化信息中静态成员数据不能被序列化,为默认值,,注意,如果在同一台机器(同一个JVM中,同一个进程)同时测试序列化和反序列化,则反序列化会直接从已经加载好的JVM中读取静态成员数据。
    2. transient是java的关键字,它只能修饰变量,而不能修改类和方法,因此在序列化对象时,将不会序列化被transient修饰的变量
  4. serialVersionUID作用:
    1. 序列化时为了验证版本一致性,保持版本兼容,在进行反序列化时,会将字节流中保存的serialVersionUID的值和本地对象的值进行比较(如果没有显示指定,会自动生成一个),如果相同则说明兼容可以反序列化,如果不相同,则会报错
    2. 序列化类如果进行兼容升级(如:新增属性),不要修改serialVersionUID字段,避免反序列化失败
    3. 如果进行不兼容升级,需要修改seriaVersionUID,避免反序列化混乱。
  5. Java有很多基础类已经实现了serializable接口,比如ArrayList等。

参考

序列化和反序列化的详解

Java序列化(Serialization)的理解

**java类中serialVersionUID的作用

*谨慎修改serialVersionUID 字段的值

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值