Java IO之序列化与反序列化详解

 更新时间:2022年01月19日 16:05:55   作者:YSOcean  
这篇文章主要为大家介绍了Java IO之序列化与反序列化,具有一定的参考价值,感兴趣的小伙伴们可以参考一下,希望能够给你带来帮助

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

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

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

2、为什么要做序列化?

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

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

3、Java 怎么进行序列化?

①、需要做序列化的对象的类,必须实现序列化接口:Java.lang.Serializable 接口(这是一个标志接口,没有任何抽象方法),Java 中大多数类都实现了该接口,比如:String,Integer

②、底层会判断,如果当前对象是 Serializable 的实例,才允许做序列化,Java对象 instanceof Serializable 来判断。

③、在 Java 中使用对象流来完成序列化和反序列化

ObjectOutputStream:通过 writeObject()方法做序列化操作

ObjectInputStream:通过 readObject() 方法做反序列化操作

第一步:创建一个 JavaBean 对象

public class Person implements Serializable{
    private String name;
    private int age;
     
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
    @Override
    public String toString() {
        return "Person [name=" + name + ", age=" + age + "]";
    }
    public Person(String name, int age) {
        super();
        this.name = name;
        this.age = age;
    }
}  
 

第二步:使用 ObjectOutputStream 对象实现序列化

//在根目录下新建一个 io 的文件夹
        OutputStream op = new FileOutputStream("io"+File.separator+"a.txt");
        ObjectOutputStream ops = new ObjectOutputStream(op);
        ops.writeObject(new Person("vae",1));
         
        ops.close();

我们打开 a.txt 文件,发现里面的内容乱码,注意这不需要我们来看懂,这是二进制文件,计算机能读懂就行了。

错误一:如果新建的 Person 对象没有实现Serializable 接口,那么上面的操作会报错:    

第三步:使用ObjectInputStream 对象实现反序列化

反序列化的对象必须要提供该对象的字节码文件.class

InputStream in = new FileInputStream("io"+File.separator+"a.txt");
        ObjectInputStream os = new ObjectInputStream(in);
        byte[] buffer = new byte[10];
        int len = -1;
        Person p = (Person) os.readObject();
        System.out.println(p);  //Person [name=vae, age=1]
        os.close();

问题1:如果某些数据不需要做序列化,比如密码,比如上面的年龄?

解决办法:在字段面前加上transient

private String name;//需要序列化
    transient private int age;//不需要序列化

那么我们在反序列化的时候,打印出来的就是Person [name=vae, age=0],整型数据默认值为 0

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

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

private static final long serialVersionUID = 8656128222714547171L;

总结

本篇文章就到这里了,希望能够给你带来帮助,也希望您能够多多关注脚本之家的更多内容!

相关文章

  • java基于AspectJ(面向切面编程)编码示例分享

    java基于AspectJ(面向切面编程)编码示例分享

    AspectJ是一种面向切面程序设计的基于Java的实现,下面对过示例学习他的使用方法,需要的朋友可以参考下
    2014-02-02
  • 解决lambda表达式内出现异常无法throw抛出的问题

    解决lambda表达式内出现异常无法throw抛出的问题

    这篇文章主要介绍了lambda表达式内出现异常无法throw抛出的解决,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-09-09
  • RocketMQ中消费者的消费进度管理

    RocketMQ中消费者的消费进度管理

    这篇文章主要介绍了RocketMQ中消费者的消费进度管理,业务实现消费回调的时候,当且仅当此回调函数返回ConsumeConcurrentlyStatus.CONSUME_SUCCESS ,RocketMQ才会认为这批消息(默认是1条)是消费完成的,需要的朋友可以参考下
    2023-10-10
  • 自己动手在Spring-Boot上加强国际化功能的示例

    自己动手在Spring-Boot上加强国际化功能的示例

    这篇文章主要介绍了自己动手在Spring-Boot上加强国际化功能的示例,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-04-04
  • MyBatis接口的简单实现原理分析

    MyBatis接口的简单实现原理分析

    这里仅仅举个简单例子来说明原理,不是完全针对MyBatis的,这种思想我们也可以应用在其他地方。地mybatis接口实现原理感兴趣的朋友一起看看吧
    2017-07-07
  • 如何在springboot中配置和使用mybatis-plus

    如何在springboot中配置和使用mybatis-plus

    这篇文章主要给大家介绍了关于如何在springboot中配置和使用mybatis-plus的相关资料,MyBatis Plus是MyBatis的增强版,旨在提供更多便捷的特性,减少开发工作,同时保留了MyBatis的灵活性和强大性能,需要的朋友可以参考下
    2023-11-11
  • 使用Maven多模块——打包指定模块

    使用Maven多模块——打包指定模块

    这篇文章主要介绍了使用Maven多模块——打包指定模块问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-09-09
  • maven插件maven-assembly-plugin打包归纳文件zip/tar使用

    maven插件maven-assembly-plugin打包归纳文件zip/tar使用

    java项目运行的文件需要jar或者war格式,同时还需要使用Java命令,本文主要介绍了maven插件maven-assembly-plugin打包归纳文件zip/tar使用,具有一定的参考价值,感兴趣的可以了解一下
    2024-02-02
  • HashSet底层竟然是HashMap实现问题

    HashSet底层竟然是HashMap实现问题

    这篇文章主要介绍了HashSet底层竟然是HashMap实现问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-07-07
  • Java实现前端jsencrypt.js加密后端解密的示例代码

    Java实现前端jsencrypt.js加密后端解密的示例代码

    这篇文章主要为大家详细介绍了如何利用jsencrypt.js实现前端加密,利用Java实现后端解密的功能,文中的示例代码讲解详细,需要的可以参考一下
    2022-09-09

最新评论