java反序列化浅探

刚打完蓝桥杯,摆!

核心类:

ObjectOutputStream:IO 类,包含序列化对象的方法,writeObject()

ObjectInputStream:IO 类,包含反序列化对象的方法,readObject()

Serializable ,接口,是一个标志性接口,标识可以在 JVM 中进行序列化,JVM 会为该类自动生成一个序列化版本号。参与序列化与反序列化的类必须实现 Serializable 接口

serialVersionUID,类属性,序列化版本号,用于给 JVM 区别同名类,没有提供版本号,JVM会默认提供序列化版本号

transient,关键字,让某些数据不参与序列化

序列化与反序列化的过程

也就是将 Java 对象对象的状态保存下来存储到文件中的过程就叫做序列化。

将硬盘中保存了 Java 对象状态的字节序列按照编号组装成对象恢复到内存中,这个过程称为反序列化。

serialVersionUID

当类名相同时,JVM 就会通过序列化版本号来区分 Java 类,序列化版本号不同就为不同的类

tips:序列化一个对象时,如果没有指定序列化版本号,后期对该类的源码进行修改并重新编译后,会导致修改前后的序列化版本号不一致,因为 JVM 会提供一个新的序列化版本号给该类对象

此时再用以往的反序列化代码去反序列化该类的对象,就会抛出异常 java.io.InvalidClassException ,所以序列化一个类时最好指定一个序列化版本号,或者永远不修改此类。

定义:

简单写法就是在首行添加

public class Student implements Serializable {
    private static final Long serialVersionUID = 1122233;
}

序列化/反序列化举例

#student
package student;
import java.io.Serializable;
public class student implements Serializable {
    private String name;
    public int age;
    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;
    }
    @Override
    public String toString() {
        return "student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
    public student(String name,int age) {
        this.name = name;
        this.age = age;
    }

}
#ser
package student;

import java.io.FileOutputStream;
import java.io.ObjectOutputStream;
public class ser {
    public static void main(String[] args) throws Exception {
student o = new student("xiaoming",12);
        ObjectOutputStream oss = new ObjectOutputStream((new FileOutputStream("student")));
        oss.writeObject(o);
        oss.flush();
        oss.close();
    }
}
#unser
package student;
import java.io.FileInputStream;
import java.io.FilterInputStream;
import java.io.ObjectInputStream;
public class unser {
    public static void main(String[] args) throws Exception {
        ObjectInputStream s =new ObjectInputStream(new FileInputStream("student"));
        Object obj = s.readObject();
        System.out.println(obj);
        s.close();
    }
}

transient 关键字

简单来说就是当你不想序列化类中某个某个属性,即可用transient去定义,这样序列化时就略过这个属性了

public class Student implements Serializable {
    private static final Long serialVersionUID = 1122233;
    private String name;
    private transient int age;//在反序列化时就不能会输出该属性,默认恢复成 null 或 0
}

在这里插入图片描述

可以看见起作用了,默认输出了null或者0;

注意事项:

说一下自己理解的小节吧:

1.序列化对象要调用ser接口

2.序列化只针对属性,不针对方法

3.最好设置一个序列化号,防止出错

4.同一对象序列化多次,只有第一次序列化为二进制流,以后都只是保存序列化编号,不会重复序列化。

5.序列化对象的引用类型成员变量,也必须是可序列化的,否则,会报错,也就是说只要进行序列化的对象,都要进行ser接口的实现

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值