Java序列化和反序列化

一、序列化的含义及作用

含义:

  1. 序列化:将Java对象转换成字节序列
  2. 反序列化:将字节序列转换成Java对象

作用:

  1. 字节序列可用于网络传输
  2. 可将Java对象持久化到存储介质中(比如硬盘)

二、序列化常用方式

1. 实现Serializable接口

要点:

  • serialVersionUID的作用是验证序列化前后对象版本一致性;
  • 静态变量 和 被 transient 修饰的变量不会被序列化。transient 只能修饰变量,不能修饰类和方法

2. 实现Externalizable接口

要点:

  • 需要提供public的无参构造方法
  • 需要实现writeExternal() 和 readExternal () 方法,且writeExternal()写入的参数类型数量大于等于readExternal()读出的
  • 特殊现象:静态变量 和 被 transient 修饰的变量测试发现可以被序列化
    (笔者暂无法解释,先抛砖引玉,请各位大神不吝赐教)

注意:Externalizable接口继承Serializable

三、演示代码

  1. 实现Serializable接口序列化测试
/**
 * @author :alen_小鹿
 * @date :Created in 2022/1/14 2:45 下午
 * @description:实现Serializable接口序列化测试
 */
/*
* 摘要:
* 一、序列化和反序列化含义及作用
* 1、含义:序列化:对象转换成字节序列;反序列化:字节序列转成对象
* 2、作用:字节序列可在网络传输;对象持久化到存储介质(比如硬盘)中
* 二、用Serializable实现序列化,有两个要点:
* 1、serialVersionUID的作用是验证序列化前后对象版本一致性;
* 2、静态变量 和 被 transient 修饰的变量不会被序列化
*
* */
public class SerializableTest implements Serializable {
    public static int age;
    public transient String address;
    public String name;
    public int money;
    private static final long serialVersionUID = 1111013L;

    public SerializableTest() {
        /**
         *
         * @description 不需要提供一个public 的无参构造方法
         * @author alen_小鹿
         * @date 2022/1/14 4:23 下午
         * @param []
         * @return
         *
         **/
        System.out.println("进入无参构造方法");
    }

    public SerializableTest(int age, String address, String name, int money) {
        System.out.println("进入有参构造方法");
        this.age = age;
        this.address = address;
        this.name = name;
        this.money = money;
    }


    @Override
    public String toString() {
        return "SerializableTest{" +
                "address='" + address + '\'' +
                ", name='" + name + '\'' +
                ", money=" + money +
                ", age='" + age + '\'' +
                '}';
    }

    public static void main(String[] args) {

        serialize();

        deserialize();

     /*
         serialVersionUID的作用是验证序列化前后对象版本一致性
         1、前后对象字段一致
            有无serialVersionUID结果一致
         2、前后对象字段不一致,
            无serialVersionUID会报错,
            有serialVersionUID时,字段以后面对象为准,值以前面对象为准。
            后面对象多的字段初始化(String 为 null,int 为 0,static修饰的字段除外,取其实际赋值)
     */

    }

    /**
     * @param
     * @return void
     * @description 序列化
     * @author alen_小鹿
     * @date 2022/1/14 2:56 下午
     **/
    public static void serialize() {

        try {
            ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("/Users/alen_小鹿/souce/svnM/TestFile/serializable.txt"));
            SerializableTest t = new SerializableTest(10, "北京", "张三", 100);
            System.out.println("序列化前对象=" + t);
            oos.writeObject(t);

            /*
                t.age = 20;
                t.setAddress("广州");
                t.setName("李四");
                t.setMoney(200);
                静态变量 和 被 transient 修饰的变量不会被序列化
                age 改成 20,静态变量不属于对象实例,不会被序列化
                address 为 null,被transient(短暂的)修饰,不会被序列化
                name 和 money 值不改,因已持久化,取持久化的旧值
            */

        } catch (IOException e) {
            System.out.println(e);
        }
    }

    /**
     * @param
     * @return void
     * @description 反序列化
     * @author alen_小鹿
     * @date 2022/1/14 2:56 下午
     **/
    public static void deserialize() {
        try {
            ObjectInputStream ois = new ObjectInputStream(new FileInputStream("/Users/alen_小鹿/souce/svnM/TestFile/serializable.txt"));
            SerializableTest t = (SerializableTest) ois.readObject();
            System.out.println("序列化后对象=" + t);
        } catch (IOException | ClassNotFoundException e) {
            System.out.println(e);
        }
    }


}

  1. 实现Externalizable接口序列化测试
/**
 * @author :alen_小鹿
 * @date :Created in 2022/1/14 3:00 下午
 * @description:实现Externalizable接口序列化测试
 */
/*
 * 摘要:Externalizable实现序列化,有两个要点:
 * 1、需要提供public的无参构造方法
 * 2、需要实现writeExternal()和readExternal()方法,且writeExternal()写入的参数类型数量大于等于readExternal()读出的
 *
 * */
public class ExternalizableTest implements Externalizable {

    public int age;
    public String address;
    public String name;
    public int money;

    private static final long serialVersionUID = 1111013L;


    /**
     * @param
     * @return
     * @description 提供一个 public 无参构造方法
     * @author alen_小鹿
     * @date 2022/1/14 4:20 下午
     **/
    public ExternalizableTest() {
        System.out.println("进入无参构造方法");
    }

    public ExternalizableTest(int age, String address, String name, int money) {
        System.out.println("进入有参构造方法");
        this.age = age;
        this.address = address;
        this.name = name;
        this.money = money;
    }


    @Override
    public String toString() {
        return "ExternalizableTest{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", money=" + money +
                ", address='" + address + '\'' +
                '}';
    }

    /**
     * @param out
     * @return void
     * @description 实现接口Externalizable的writeExternal方法
     * @author alen_小鹿
     * @date 2022/1/14 4:21 下午
     **/
    @Override
    public void writeExternal(ObjectOutput out) throws IOException {

        System.out.println("序列化写入");
        out.writeObject(name);
        out.writeInt(age);
        out.writeObject(address);
    }

    /**
     * @param in
     * @return void
     * @description 实现接口Externalizable的readExternal方法
     * @author alen_小鹿
     * @date 2022/1/14 4:21 下午
     **/
    @Override
    public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
        System.out.println("反序列化读出");
        name = (String) in.readObject();
        age = in.readInt();
    }

    public static void main(String[] args) {
        enternalize();
        deEnternalize();
    }

    /**
     * @param
     * @return void
     * @description 序列化写入
     * @author alen_小鹿
     * @date 2022/1/14 4:19 下午
     **/
    public static void enternalize() {

        try {
            ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("/Users/alen_小鹿/souce/svnM/TestFile/enternalizable.txt"));
            ExternalizableTest t = new ExternalizableTest(10, "北京", "张三", 100);
            oos.writeObject(t);
            System.out.println("序列化前对象=" + t);
        } catch (IOException e) {
            System.out.println(e);
        }
    }

    /**
     * @param
     * @return void
     * @description 反序列化读出
     * @author alen_小鹿
     * @date 2022/1/14 4:19 下午
     **/
    public static void deEnternalize() {

        try {
            ObjectInputStream ois = new ObjectInputStream(new FileInputStream("/Users/alen_小鹿/souce/svnM/TestFile/enternalizable.txt"));
            ExternalizableTest t = (ExternalizableTest) ois.readObject();
            System.out.println("序列化后对象=" + t);
        } catch (IOException | ClassNotFoundException e) {
            System.out.println(e);
        }
    }


}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值