java 序列化与反序列化

什么是序列化与反序列化?

  序列化:指把堆内存中的 Java 对象数据,通过某种方式把对象存储到磁盘文件中或者传递给其他网络节点(在网络上传输)。这个过程称为序列化。通俗来说就是将数据结构或对象转换成二进制串的过程

  反序列化:把磁盘文件中的对象数据或者把网络节点上的对象数据,恢复成Java对象模型的过程。也就是将在序列化过程中所生成的二进制串转换成数据结构或者对象的过程
  这里写图片描述

序列化用途

  ①、在分布式系统中,此时需要把对象在网络上传输,就得把对象数据转换为二进制形式,需要共享的数据的 JavaBean 对象,都得做序列化。

  ②、服务器钝化:如果服务器发现某些对象好久没活动了,那么服务器就会把这些内存中的对象持久化在本地磁盘文件中(Java对象转换为二进制文件);如果服务器发现某些对象需要活动时,先去内存中寻找,找不到再去磁盘文件中反序列化我们的对象数据,恢复成 Java 对象。这样能节省服务器内存

java实现序列化

通过这个两个对象进行序列化操作
import java.io.FileOutputStream;
import java.io.ObjectInputStream;

其中对应方法(这里用到读取Object)
这里写图片描述
实现 java.io.Serializable 接口

package io.domain;

import java.io.Serializable;

public class Person implements Serializable {
    private String name;
    private int age;

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

    @Override
    public String toString() {
        return "Person [name=" + name + ", age=" + age + "]";
    }

}

测试

package io;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;

import io.domain.Person;

public class DriveTest2 {

    public static void main(String[] args) throws Exception {
        Person person = new Person("张三", 11);

        //当前工程根目录
        FileOutputStream fos = new FileOutputStream("a.txt");
        ObjectOutputStream oos =new ObjectOutputStream(fos);
        oos.writeObject(person);   //序列化
        oos.close();

        FileInputStream fis = new FileInputStream("a.txt");
        ObjectInputStream ois = new ObjectInputStream(fis);
        Object object = ois.readObject();   //反序列化
        if (object instanceof Person) {
            Person person2 = (Person) object;
            System.out.println(person2.toString());
        }
        fis.close();
    }
}

测试结果

Person [name=张三, age=11]

java实现序列化注意事项

不实现 java.io.Serializable 接口

抛出异常

Exception in thread "main" java.io.NotSerializableException: io.domain.Person
    at java.io.ObjectOutputStream.writeObject0(Unknown Source)
    at java.io.ObjectOutputStream.writeObject(Unknown Source)
    at io.DriveTest2.main(DriveTest2.java:18)
transient 字段不序列化

去除不需要序列化的字段

package io.domain;

import java.io.Serializable;

public class Person implements Serializable {

    public static String staticString = "staticString";

    private transient String name;
    private int age;

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

    @Override
    public String toString() {
        return "Person [name=" + name + ", age=" + age + "]";
    }

}

测试

package io;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;

import io.domain.Person;

public class DriveTest2 {

    public static void main(String[] args) throws Exception {
        Person person = new Person("张三", 11);
        System.out.println(Person.staticString);

        //当前工程根目录
        FileOutputStream fos = new FileOutputStream("a.txt");
        ObjectOutputStream oos =new ObjectOutputStream(fos);
        oos.writeObject(person);   //序列化
        oos.close();

        FileInputStream fis = new FileInputStream("a.txt");
        ObjectInputStream ois = new ObjectInputStream(fis);
        Object object = ois.readObject();   //反序列化
        if (object instanceof Person) {
            Person person2 = (Person) object;
            System.out.println(person2.toString());
            System.out.println(person2.staticString);
        }
        fis.close();
    }
}

测试结果

staticString
Person [name=null, age=11]
staticString
serialVersionUID 字段作用

序列化版本问题,在完成序列化操作后,由于项目的升级或修改,可能我们会对序列化对象进行修改,比如增加某个字段,那么我们在进行反序列化就会报错:

Exception in thread "main" java.io.InvalidClassException: io.domain.Person; local class incompatible: stream classdesc serialVersionUID = -14444189870184359, local class serialVersionUID = 155460768953663504
    at java.io.ObjectStreamClass.initNonProxy(Unknown Source)
    at java.io.ObjectInputStream.readNonProxyDesc(Unknown Source)
    at java.io.ObjectInputStream.readClassDesc(Unknown Source)
    at java.io.ObjectInputStream.readOrdinaryObject(Unknown Source)
    at java.io.ObjectInputStream.readObject0(Unknown Source)
    at java.io.ObjectInputStream.readObject(Unknown Source)
    at io.DriveTest2.main(DriveTest2.java:21)

解决办法:在 JavaBean 对象中增加一个 serialVersionUID 字段,用来固定这个版本,无论我们怎么修改,版本都是一致的,就能进行反序列化了

private static final long serialVersionUID = 1L;
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值