java IO流六:序列化 & 反序列化 、序列化版本号

序列化 & 反序列化

序列化应用场景:
比如你用电脑在淘宝上购物,当你准备付款时电脑断电了,此时在服务器端已经创建对象。
服务器端会这个保留对象一段时间,如果这是用户还未进行相关处理,服务器为了减少资源
消耗,就会将这个对象写入硬盘中。将内存中对象写入硬盘中的过程叫做 序列化。

序列化ObjectOutputStream

package com.company01.IO;
/*
    java.io.ObjectOutputStream; 序列化JAVA对象到硬盘。(Serial)
    java.io.ObjectInputStream; 将硬盘中的数据“反序列化”到内存。(DeSerial)

    Compile 编译(java --> Class文件)
    DeCompile 反编译(Class --> java文件)
*/
import java.io.*;
import java.io.Serializable;  // 该接口是一个"可序列化"的
                              // 该接口没有任何方法,是一个标识接口
                              // 像这样的接口还有:java.lang.Cloneable; 可克隆的

public class ObjectOutputStreamTest01 {
    public static void main(String[] args) throws Exception{

        // 1.创建java对象
        User u1 = new User("刘德华");

        // 2.创建输出流(序列化流)(JVM中的java对象状态保存到硬盘中)
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("test04"));

        // 3.写
        oos.writeObject(u1);

        // 刷新
        oos.flush();
        // 关闭
        oos.close();
    }
}

/*
    标识接口的作用:起到标识的作用。
    JVM如果看到该对象实现了某个标识接口,会对它特殊待遇。

    疑问:User实现Serializable接口,JVM对它的特殊待遇是什么?
*/
class User implements Serializable{
    String name;

    User(String name){
        this.name = name;
    }

    public String toString(){
        return "User[name:" + name + "]";
    }
}

反序列化ObjectInputStream

package com.company01.IO;
/*
    反序列化
*/
import java.io.*;
public class ObjectInputStreamTest01 {
    public static void main(String[] args) throws Exception{

        // 1,创建反序列化流
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream("test04"));

        // 2.反序列化
        Object o = ois.readObject();

        System.out.println(o);  // 默认调用o.toString()

        // 关闭
        ois.close();
    }
}

序列化版本号

package com.company01.serialVersionUID;

import java.io.Serializable;

/*
    因为User实现了Serializable接口,JVM会特殊待遇:
        会给该类添加一个属性,static final long serialVersionUID = xxx...;
        当类发生改变后,该属性值会发生改变。

    可以不让系统自动生成,自己直接写一个序列化版本号
*/
public class User implements Serializable{

    // 可以不让系统自动生成,自己直接写一个序列化版本号
    static final long serialVersionUID = -294795583033464129L;

    String name;

    // 如果不想让该属性参加序列化,需要使用trainsient关键字修饰
    // 被trainsient关键字修饰的属性,在反序列化的时候,所有对象中该属性值都默认为 该属性类型类型的默认初始化值(int:0;String:null;...)。
    transient int age;

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

    public String toString(){
        return "User[name:" + name + ",age:" + age + "]";
    }
}

package com.company01.serialVersionUID;

import java.io.*;

// 序列化
public class Test01 {
    public static void main(String[] args) throws Exception{

        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("user.DBF")); // DBF数据库文件

        User u = new User("zhangsan", 23);

        oos.writeObject(u);

        oos.flush();

        oos.close();
    }
}

package com.company01.serialVersionUID;
/*
    当User.java改变后编译,生成的User.Class文件发生改变
    在没有重新进行序列化的倩况下,执行先前的反序列化,会报错

    Exception in thread "main" java.io.InvalidClassException: com.company01.serialVersionUID.User;
    local class incompatible:
    stream classdesc serialVersionUID = -294795583033464129,   流里面的class描述用的序列化版本号
    local class serialVersionUID = -1356840406334401512        本地的class文件中序列化版本号
    当两个版本号不一致时,JVM认为是不兼容的两个类。

    因为User实现了Serializable接口,JVM会特殊待遇:
        会给该类添加一个属性,static final long serialVersionUID = xxx...;
        当类发生改变后,该属性值会发生改变。

*/
import java.io.*;
// 反序列化
public class Test02 {
    public static void main(String[] args) throws Exception{

        ObjectInputStream ois = new ObjectInputStream(new FileInputStream("user.DBF"));

        System.out.println(ois.readObject());

        ois.close();
    }
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值