一文带你彻底理解Java序列化和反序列化

作者:mySoul 时间:2021-12-23 05:24:12 

Java序列化是什么?

Java序列化是指把Java对象转换为字节序列的过程,Java反序列化是指把字节序列恢复为Java对象的过程。

反序列化: 客户端重文件,或者网络中获取到文件以后,在内存中重构对象。

序列化: 对象序列化的最重要的作用是传递和保存对象的时候,保证对象的完整性和可传递性。方便字节可以在网络上传输以及保存在本地文件。

为什么需要序列化和反序列化

实现分布式

核心在于RMI,可以利用对象序列化运行远程主机上的服务,实现运行的时候,就像在本地上运行Java对象一样。

实现递归保存对象

进行序列化的时候,单单并不是保存一个对象,而是递归的保存一整个对象序列,即递归保存,通过反序列化,可以递归的得到一整个对象序列。

序列信息可以永久保存

用于序列化的信息,可以永久保存为文件,或者保存在数据库中,在使用的时候,再次随时恢复到内存中,实现内存中的类的信息可以永久的保存。

数据格式统一

比照Linux的一切皆文件的思想,同时Java也是这样的思想,让数据格式尽可能的统一,让对象,文件,数据,等等许许多多不同的格式,都让其统一,以及保存。实现数据可以完整的传输和保存。然后进行反序列化还原,即,对象还是对象,文件还是文件。

实现Java序列化和反序列化

要进行反序列化需要实现一个接口。即 Serializabei接口。

代码如下

需要转化的类


package common.lang;

import java.io.Serializable;

import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;

public class User1 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 new ToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE)
        .append("name", name)
        .append("age", age)
        .toString();
}
}

进行序列化,以及反序列化


package common.lang;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;

public class SerializableDemo1 {

public static void main(String[] args) throws Exception, IOException {
 //初始化对象
 User1 user = new User1();
 user.setName("yaomy");
 user.setAge(23);
 System.out.println(user);
 //序列化对象到文件中
 ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("template"));
 oos.writeObject(user);
 oos.close();
 //反序列化
 File file = new File("template");
 ObjectInputStream ois = new ObjectInputStream(new FileInputStream(file));
 User1 newUser = (User1)ois.readObject();
 System.out.println(newUser.toString());
}
}

另一个序列化接口 Externalizable

继续实现Externalizable接口


package common.lang;

import java.io.Externalizable;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectOutput;

import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;

public class User1 implements Externalizable{

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 new ToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE)
        .append("name", name)
        .append("age", age)
        .toString();
}
@Override
public void writeExternal(ObjectOutput out) throws IOException {
 // TODO Auto-generated method stub

}
@Override
public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
 // TODO Auto-generated method stub

}
}

进行序列化以及反序列化


package common.lang;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;

public class SerializableDemo1 {

public static void main(String[] args) throws Exception, IOException {
 //初始化对象
 User1 user = new User1();
 user.setName("yaomy");
 user.setAge(23);
 System.out.println(user);
 //序列化对象到文件中
 ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("template"));
 oos.writeObject(user);
 oos.close();
 //反序列化
 File file = new File("template");
 ObjectInputStream ois = new ObjectInputStream(new FileInputStream(file));
 User1 newUser = (User1)ois.readObject();
 System.out.println(newUser.toString());
 ois.close();
}
}

查看输出的结构

common.lang.User1@6ef64f64[
name=yaomy
age=23
]
common.lang.User1@184c9860[
name=<null>
age=0
]

根据输出的结果可以看到,对User1进行序列化然后再反序列化之后对象的属性都恢复成了默认值,即,之前那个对象的状态没有被持久保存下来,这就是Externalization和Serialization接口的区别,其中前者接口会被恢复成为默认值,后者接口不会恢复默认值。

如果需要恢复,这里就需要重写两个抽象方法,分别是writeExternal与readExternal两个抽象方法。


package common.lang;

import java.io.Externalizable;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectOutput;

import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;

public class User1 implements Externalizable{

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 new ToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE)
        .append("name", name)
        .append("age", age)
        .toString();
}
@Override
public void writeExternal(ObjectOutput out) throws IOException {
 out.writeObject(name);
 out.writeInt(age);

}
@Override
public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
 name = (String)in.readObject();
 age = in.readInt();

}
}

package common.lang;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;

public class SerializableDemo1 {

public static void main(String[] args) throws Exception, IOException {
 //初始化对象
 User1 user = new User1();
 user.setName("yaomy");
 user.setAge(23);
 System.out.println(user);
 //序列化对象到文件中
 ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("template"));
 oos.writeObject(user);
 oos.close();
 //反序列化
 File file = new File("template");
 ObjectInputStream ois = new ObjectInputStream(new FileInputStream(file));
 User1 newUser = (User1)ois.readObject();
 System.out.println(newUser.toString());
 ois.close();
}
}

输出的结果

common.lang.User1@6cd66725[
name=yaomy
age=23
]
common.lang.User1@19160e64[
name=yaomy
age=23
]

静态变量的序列化

实例


public class Test implements Serializable {

private static final long serialVersionUID = 1L;

public static int staticVar = 5;

public static void main(String[] args) {
 try {
  //初始时staticVar为5
  ObjectOutputStream out = new ObjectOutputStream(
    new FileOutputStream("result.obj"));
  out.writeObject(new Test());
  out.close();

//序列化后修改为10
  Test.staticVar = 10;

ObjectInputStream oin = new ObjectInputStream(new FileInputStream(
    "result.obj"));
  Test t = (Test) oin.readObject();
  oin.close();

//再读取,通过t.staticVar打印新的值
  System.out.println(t.staticVar);

} catch (FileNotFoundException e) {
  e.printStackTrace();
 } catch (IOException e) {
  e.printStackTrace();
 } catch (ClassNotFoundException e) {
  e.printStackTrace();
 }
}
}

代码阐述一下过程,在main方法中,对象序列化以后,修改静态变量的数值,再把序列化后的对象读取出来,此时输出的值为10.

理解如下: 打印的staticVar是从读取对象里获得的,打印10的原因是因为序列化时,不保存静态变量,只保存内存中的状态。此时修改静态变量的值,修改的是类中的值,输出的也是类中的值,和内存无关。

Transient关键字

Transient关键字,加上以后,可以阻止该变量被序列化到文件中,反序列化以后,变量的值设定为初始值。

来源:https://www.tuicool.com/articles/fUrEj2n

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

猜你喜欢

  • java 创建自定义数组

    2022-09-02 11:18:45
  • Java开源工具iText生成PDF简单实例

    2022-09-12 15:06:54
  • Java基于socket实现简易聊天室实例

    2021-10-30 00:24:56
  • 教你怎么用java一键自动生成数据库文档

    2021-08-01 02:34:36
  • 如何基于Java实现对象List排序

    2022-01-28 03:59:16
  • 全面总结java IO体系

    2023-05-16 13:19:12
  • c#用for语句输出一个三角形的方法

    2023-12-17 05:46:53
  • 利用Java计算某个日期是星期几

    2023-11-17 05:49:42
  • JAVA NIO实现简单聊天室功能

    2023-05-01 10:32:49
  • springboot整合Shiro

    2022-11-13 11:07:52
  • Android RecyclerBarChart绘制使用教程

    2023-06-19 12:18:36
  • java web个人通讯录系统设计

    2022-09-14 11:12:15
  • 图文详解Maven工程打jar包的N种方式

    2022-12-12 21:36:23
  • 带你详细了解Java值传递和引用传递

    2023-02-19 08:42:26
  • Java如何去掉指定字符串的开头的指定字符

    2022-05-23 13:28:31
  • java中单例模式讲解

    2022-05-22 14:24:07
  • 再谈异常处理try catch finally

    2021-11-12 11:17:31
  • Mybatis-Plus的多数据源你了解吗

    2023-07-22 00:46:59
  • C#如何将DataTable导出到Excel解决方案

    2022-03-30 18:44:28
  • SpringBoot整合Quartz实现定时任务详解

    2021-11-22 06:40:57
  • asp之家 软件编程 m.aspxhome.com