Java 对象序列化流

在学习对象序列化流之前,我们先解释一下什么序列化和反序列化

序列化:把对象当做字节写入文件
反序列化:把文件中的对象读取出来

简单说对象序列化流就是用来写对象和读对象的。Java提供了ObjectOuputStream用来写对象;ObjectInputStream用来读对象。

ObjectOutputStream是OutputStream的子类,写对象时需要依赖于FileOutputStream;

ObjectInputStream是InputStream的子类,写对象时需要依赖于FileInputStream.

还需要注意的是Java语言规定,必须让序列化对象的类,实现一个名为Serializable的接口,才能被序列化。Serializable的接口不包含任何方法和字段,仅仅起到标记的作用。

定义Student类并实现Serializable接口

//让Student类实现了Serializable
public class Student implements Serializable{
    //成员变量
    private String name;
    private int age;
    //构造方法
    public Student(){}
    public Student(String name,int age){
        this.name=name;
        this.age=age;
    }
    //...省略若干行代码...
}

序列化

Student对象序列化到C:\io\a.txt文件中

public class ObjectOutputStreamDemo{
    public static void main(String[] args){
        //创建流对象
        ObjectOutputStreamS oos=new ObjectOuputStream(new FileOutputStream("C:\io\a.txt"));

        //创建Student对象
        Student s1=new Student("孙悟空",500);
        oos.writeObject(s1);

        //释放资源
        oos.close();
    }
}

反序列化

C:\io\a.txt文件中反序列化得到Student对象

public class ObjectInputStream {
    public static void main(String[] args) {
        //反序列化流
        ObjectInputStream ois=new ObjectInputStream(new FileInputStream("day10-code\\a.txt"));
        //读取对象
        Student s2 = (Student) ois.readObject();
        System.out.println(s2);
        //释放资源
        ois.close();
    }
}

序列号问题

如果序列化后又改动了Student类文件,这个时候再反序列化就会出现序列号版本不一致的问题

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-R8hKub0t-1591169867294)(assets/2019-07-15-15-54-02.png)]

序列号问题解析

如图,每次编译都会生成给字节码文件生成一个序列号,当序列化该类对象时,也会保存序列号信息。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-pdq8fMFN-1591169867296)(assets/2019-07-15-16-03-32.png)]

如果改变了源代码会重新编码并且生成新的序列号,这时候反序列化,就会造成存储对象的序列号和新的序列号版本不一致,就会出现InvalidClassException:异常

解决序列号问题

解决序列号不一致的问题很简单,只需要把序列号固定下来就可以了。在Student类中加上下面的一句代码,重新序列化即可。

public class Student implements Serializable {
    //固定序列号
    private static final long serialVersionUID = -123455678L;
    //成员变量
    private String name;
    private  int age;
    //....省略若干代码...
}

瞬态

如果有某个成员变量不想被序列化,可以使用transient瞬态关键字修饰(也别管瞬态是什么意思,就这么个读法);

如我不想Studentage属性被序列化,就可以使用transient修饰age属性

public class Student implements Serializable {
    //固定序列号
    private static final long serialVersionUID = -123455678L;
    //成员变量
    private String name;

    //age属性不被序列化
    private transient  int age;
    //....省略若干代码...
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值