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

作者:YSOcean 时间:2023-05-21 14:59:14 

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

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

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

2、为什么要做序列化?

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

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

3、Java 怎么进行序列化?

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

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

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

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

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

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

第一步:创建一个 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 接口,那么上面的操作会报错:

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

第三步:使用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:序列化版本问题,在完成序列化操作后,由于项目的升级或修改,可能我们会对序列化对象进行修改,比如增加某个字段,那么我们在进行反序列化就会报错:

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

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

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

private static final long serialVersionUID = 8656128222714547171L;

来源:https://www.cnblogs.com/ysocean/p/6870069.html

标签:Java,IO,序列化,反序列化
0
投稿

猜你喜欢

  • Java二维数组查找功能代码实现

    2023-01-04 19:47:17
  • 浅谈@FeignClient中name和value属性的区别

    2023-11-06 13:04:14
  • Spring实战之属性覆盖占位符配置器用法示例

    2023-02-02 00:05:30
  • c# AcceptEx与完成端口(IOCP)结合的示例

    2023-07-29 01:46:24
  • Mybatis之typeAlias配置的3种方式小结

    2023-11-26 16:42:14
  • java 中String.equals和==的比较

    2023-03-09 08:45:16
  • 一个Servlet是如何处理多个请求的?

    2023-01-18 11:19:32
  • 详解spring security之httpSecurity使用示例

    2023-08-03 09:46:17
  • Java 数据结构与算法系列精讲之二叉堆

    2022-05-14 06:31:15
  • Spring Boot统一处理全局异常的实战教程

    2023-11-24 20:51:34
  • mybatis注入Date日期值为null的解决方法

    2021-12-08 01:49:17
  • Java的RxJava库操作符的用法及实例讲解

    2021-12-14 22:31:41
  • 详解Java实践之建造者模式

    2023-01-14 23:03:13
  • 使用Spring Data Redis实现数据缓存的方法

    2021-08-02 10:19:25
  • Spring创建bean的几种方式及使用场景

    2021-06-20 14:16:35
  • Java实现自动压缩文件并加密的方法示例

    2023-05-08 03:33:18
  • Java8中Stream的一些神操作

    2021-11-18 19:07:21
  • JVM中有哪些内存区域及其作用

    2023-07-13 05:28:33
  • List调用toString()方法后,去除两头的中括号实例

    2023-09-28 11:18:56
  • java ThreadLocal使用案例详解

    2022-02-01 05:14:57
  • asp之家 软件编程 m.aspxhome.com