讲解一下java中的序列化和反序列化

序列化和反序列化几乎是工程师们每天都要面对的事情,但是要精确掌握这两个概念并不容易:一方面,它们往往作为框架的一部分出现而湮没在框架之中;另一方面,它们会以其他更容易理解的概念出现,例如加密、持久化。然而,序列化和反序列化的选型却是系统设计或重构一个重要的环节,在分布式、大数据量系统设计里面更为显著。

1、什么是序列化?为什么要序列化?

Java 序列化就是指将对象转换为字节序列的过程,而反序列化则是只将字节序列转换成目标对象的过程。

我们都知道,在进行浏览器访问的时候,我们看到的文本、图片、音频、视频等都是通过二进制序列进行传输的,那么如果我们需要将Java对象进行传输的时候,是不是也应该先将对象进行序列化?答案是肯定的,我们需要先将Java对象进行序列化,然后通过网络,IO进行传输,当到达目的地之后,再进行反序列化获取到我们想要的对象,最后完成通信。

2、如何实现序列化

2.1、使用到JDK中关键类 ObjectOutputStream 和ObjectInputStream

ObjectOutputStream 类中:通过使用writeObject(Object object) 方法,将对象以二进制格式进行写入。

ObjectInputStream 类中:通过使用readObject()方法,从输入流中读取二进制流,转换成对象。

**2.2、目标**对象需要先实现 Seriable接口

我们创建一个Student类:

public class Student implements Serializable {
   private static final long serialVersionUID = 3404072173323892464L;
   private String name;
   private transient String id;
   private String age;

   @Override
   public String toString() {
       return "Student{" +
               "name='" + name + '\'' +                ", id='" + id + '\'' +                ", age='" + age + '\'' +
               '}';
   }

   public String getAge() {
       return age;
   }

   public void setAge(String age) {
       this.age = age;
   }

   public Student(String name, String id) {
       System.out.println("args Constructor");
       this.name = name;
       this.id = id;
   }

   public Student() {
       System.out.println("none-arg Constructor");
   }

   public String getName() {
       return name;
   }

   public void setName(String name) {
       this.name = name;
   }

   public String getId() {
       return id;
   }

   public void setId(String id) {
       this.id = id;
   }

}

代码中Student类实现了Serializable 接口,并且生成了一个版本号:

private` `static` `final` `long` `serialVersionUID = 3404072173323892464L;

首先:

1、Serializable 接口的作用只是用来标识我们这个类是需要进行序列化,并且Serializable 接口中并没有提供任何方法。

2、serialVersionUid 序列化版本号的作用是用来区分我们所编写的类的版本,用于判断反序列化时类的版本是否一直,如果不一致会出现版本不一致异常。

3、transient 关键字,主要用来忽略我们不希望进行序列化的变量

2.3、将对象进行序列或和反序列化

2.3.1 第一种写入方式:

public static  void main(String[] args){
       File file = new File("D:/test.txt");
       Student student = new Student("孙悟空","12");
       try {
           ObjectOutputStream outputStream = new ObjectOutputStream(new FileOutputStream(file));
           outputStream.writeObject(student);
           outputStream.close();
       } catch (IOException e) {
           e.printStackTrace();
       }

       try {
           ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream(file));
           Student s = (Student) objectInputStream.readObject();
           System.out.println(s.toString());
           System.out.println(s.equals(student));
       } catch (IOException e) {
           e.printStackTrace();
       } catch (ClassNotFoundException e) {
           e.printStackTrace();
       }
   }

创建对象Student ,然后通过ObjectOutputStream类中的writeObject()方法,将对象输出到文件中。

然后通过ObjectinputStream 类中的readObject()方法反序列化,获取对象。

2.3.2 第二种写入方式:

在Student 类中实现writeObject()和readObject()方法:

  private void writeObject(ObjectOutputStream objectOutputStream) throws IOException {
       objectOutputStream.defaultWriteObject();
       objectOutputStream.writeUTF(id);

   }

   private void readObject(ObjectInputStream objectInputStream) throws IOException, ClassNotFoundException {
       objectInputStream.defaultReadObject();
       id = objectInputStream.readUTF();
   }

通过这中方式进行序列话,我们可以自定义想要进行序列化的变量,将输入流和输出流传入对线实例中,然后进行序列化以及反序列化。

2.3.3 第三种写入方式:

Student 实现 *Externalnalizable接口 而不实现Serializable 接口*

*Externaliable 接口是 Serializable 的子类,有着和Serializable接口同样的功能:*

public class Student implements Externalizable {
   private static final long serialVersionUID = 3404072173323892464L;
   private String name;
   private transient String id;
   private String age;

   @Override
   public String toString() {
       return "Student{" +
               "name='" + name + '\'' +                ", id='" + id + '\'' +                ", age='" + age + '\'' +
               '}';
   }

   public String getAge() {
       return age;
   }

   public void setAge(String age) {
       this.age = age;
   }

   public Student(String name, String id) {
       System.out.println("args Constructor");
       this.name = name;
       this.id = id;
   }

   public Student() {
       System.out.println("none-arg Constructor");
   }

   public String getName() {
       return name;
   }

   public void setName(String name) {
       this.name = name;
   }

   public String getId() {
       return id;
   }

   public void setId(String id) {
       this.id = id;
   }


   @Override
   public void writeExternal(ObjectOutput out) throws IOException {
       out.writeObject(name);
       out.writeObject(id);
   }

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

}

通过和前面的第二种写入方法对比,我们可以发现他们的实现原理都是十分的类似,不过实现Externalnalizable接口 并不支持第一种序列化方法,它只能够通过实现接口中的writeExternal()和readExternal()方法实现对象的序列化。

3、面试中关于序列化的问题:

1、什么是序列化,如何实现序列化

java中对象的序列化就是将对象转换成二进制序列,反序列化则是将二进制序列转换成对象

Java 实现序列化有多种方式

1、首先需要使用到工具类ObjectInputStream 和ObjectOutputStream 两个IO类

2、实现Serializable 接口:

有两种具体序列化方法:

2.1 直接通过ObjectOutputStream 和 ObjectInputStream 类中的 writeObject()和readObject()方法

2.2 通过在序列化对象中实现writeObject()和readObject()方法,传入ObjectOutputStream和ObjectInputStream对象,完成序列化

3、实现Externalizable 接口:

文章来源网络,作者:管理,如若转载,请注明出处:https://shuyeidc.com/wp/220313.html<

(0)
管理的头像管理
上一篇2025-04-14 12:35
下一篇 2025-04-14 12:37

相关推荐

  • 站群服务器和普通服务器到底哪个更适合GEO,怎么选?

    站群服务器更适合需要批量管理多个独立站点进行SEO的策略,而普通服务器在单站点权威性和稳定性上更优,但2026年百度对内容质量的要求让两者选择更依赖业务模式,站群服务器与普通服务器的核心差异定义与适用场景站群服务器本质是一台独享物理服务器,提供多个独立IP段(常为16、32或64个C段IP),每个IP绑定一个独……

    2026-07-28
    0
  • 物理服务器和云服务器做站群到底选哪个,哪个更稳定?

    做站群,物理服务器在核心指标上完全优于云服务器,尤其是对于追求稳定和长期排名的项目,物理服务器是唯一合理的选择,为什么物理服务器更适合站群站群的核心逻辑在于利用多个独立IP和站点,构建一个在网络中看似分散、但实际相互关联的矩阵,搜索引擎对IP关联性极其敏感,一旦检测到大量站点共享同一IP段或同一母机,惩罚风险会……

    2026-07-28
    0
  • 国内高防服务器哪家防御真实靠谱,怎么选?

    国内高防服务器哪家防御真实靠谱?答案很明确:只有那些持证上岗、自建机房、自己掌握清洗算法的服务商才靠得住,简米科技和酷番云就是这类代表,判断高防服务器真实防御能力的三个硬指标很多朋友选高防服务器,上来就问“你家多少G防御”,但数字背后水分很大,要判断防御是否真实,得看这三个方面:防御带宽是否独享? 有些服务商宣……

    2026-07-28
    0
  • 裸金属服务器和物理服务器有什么区别?,怎么选?

    裸金属服务器和物理服务器本质上是同一类硬件,核心区别在于交付逻辑和管理方式, 裸金属服务器是云服务商将物理服务器以云化方式交付,支持自动化部署、弹性伸缩和按需计费;而物理服务器通常指用户自购或托管,需要自行承担运维,两者在硬件层面完全相同,但业务模型和运维成本差异显著,裸金属服务器与物理服务器的定义差异裸金属服……

    2026-07-28
    0
  • 做GEO站群选哪家服务器服务商靠谱,怎么选?

    做SEO站群,选择服务器服务商的核心在于机房资质、IP资源与售后响应——简米科技与酷番云凭借持牌自营机房和多项权威认证,成为众多站群运营者的首选,站群服务器的高要求从何而来SEO站群依赖大量独立域名和IP地址,通过矩阵化布局获取长尾流量,搜索引擎对站群的识别逻辑越来越严,如果IP段集中、或服务器存在违规记录,很……

    2026-07-28
    0

发表回复

您的邮箱地址不会被公开。必填项已用 * 标注