知识改变命运! java高频面试题-Java如何实现序列化和反序列化?_猿份哥-lskyf博客社区

java高频面试题-Java如何实现序列化和反序列化?

猿份哥 6月前 ⋅ 732 阅读 ⋅ 2 个赞

一.为什么要序列化?

序列化为数据持久化、远程通信、数据交换和对象复制提供了便捷的解决方案。它是在不同系统间共享和传递对象的一种常用方法。

几个常见原因:

持久化数据: 将对象序列化后存储在文件系统或数据库中,使数据在应用关闭或重启后仍然存在。这种持久化允许数据在不同的时间和地点之间持久保存。

网络传输: 序列化的字节流可在网络中传输。在分布式系统中,对象序列化后可以在不同的节点间传递,支持远程通信和数据交换。

跨平台通信: 通过序列化,可以使数据跨不同的平台和编程语言进行交互。例如,在使用JSON、XML或Protocol Buffers时,不同系统能够解析和操作序列化的数据。

对象克隆: 通过序列化和反序列化,可以快速克隆一个对象,特别是在需要对象副本而不想手动复制对象时非常有用。

缓存和缓存共享: 序列化允许对象缓存到持久存储或共享缓存中,以便将来快速获取,减少重复对象创建和初始化的开销。

二.有哪些实现方式?各自的使用场景是哪些?

1.Serializable接口:

通过实现java.io.Serializable接口,对象可以被序列化。这是Java内置的序列化机制,可以使用ObjectOutputStream进行对象序列化,ObjectInputStream进行反序列化。

示例代码:

import java.io.*;
//类实现Serializable接口
public class MyClass implements Serializable {
    public static final long serialVersionUID =1L;
    private int id;
    private String name;
    // get,set,构造方法略
}

// 序列化示例
MyClass obj = new MyClass();
try {
    FileOutputStream fileOut = new FileOutputStream("file.ser");
    ObjectOutputStream out = new ObjectOutputStream(fileOut);
    out.writeObject(obj);
    out.close();
    fileOut.close();
} catch (IOException e) {
    e.printStackTrace();
}

// 反序列化示例
MyClass obj;
try {
    FileInputStream fileIn = new FileInputStream("file.ser");
    ObjectInputStream in = new ObjectInputStream(fileIn);
    obj = (MyClass) in.readObject();
    in.close();
    fileIn.close();
} catch (IOException | ClassNotFoundException e) {
    e.printStackTrace();
}

2.Externalizable接口:

另一个接口java.io.Externalizable允许你自定义序列化过程。这需要实现writeExternal()和readExternal()方法来手动管理对象的序列化和反序列化过程。

import java.io.*;

public class MyClass implements Externalizable {
    private int id;
    private String name;
    // get,set,构造方法略

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

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

// 序列化和反序列类似Serializable


3.JSON序列化:

使用第三方库如Jackson、Gson、Fastjson等,将对象转换为JSON格式进行序列化和反序列化。这种方式不依赖Java的内置序列化机制,提供了更灵活的序列化和反序列化过程。

import com.fasterxml.jackson.databind.ObjectMapper;

public class MyClass {
    private int id;
    private String name;
    // get,set,构造方法略
}

// 序列化
MyClass obj = new MyClass();
ObjectMapper mapper = new ObjectMapper();
String json = mapper.writeValueAsString(obj);

// 反序列化
MyClass obj = mapper.readValue(json, MyClass.class);


4.XML序列化:

同样可以使用第三方库,比如JAXB(Java Architecture for XML Binding)来实现将对象序列化为XML格式,并进行反序列化。

import javax.xml.bind.*;

class MyClass {
    private int id;
    private String name;
    // get,set,构造方法略
}

// 反序列化
MyClass obj = new MyClass();
JAXBContext context = JAXBContext.newInstance(MyClass.class);
Marshaller marshaller = context.createMarshaller();
marshaller.marshal(obj, new File("output.xml"));

// 序列化
MyClass obj = (MyClass) context.createUnmarshaller().unmarshal(new File("output.xml"));


5.Protocol Buffers:

由Google开发的一种序列化框架,使用.proto文件定义数据结构,提供了高效的序列化和反序列化。

需要通过.proto文件定义数据结构,并使用相应的生成工具生成Java类。例子较为复杂,需要编写.proto文件,并通过Protocol Buffers工具生成Java类。

6.Kryo和Hessian:

第三方库如Kryo和Hessian提供了替代Java默认序列化机制的选择,它们通常更快速、更紧凑。

Kryo和Hessian:这些库的使用方式类似于Serializable接口,不同之处在于引入相应的库类,例如使用Kryo库。

三.各自的优势和不足

Serializable接口:

优势:简单易用,Java内置支持。 不足:性能较低,不适用于跨语言。

JSON序列化:

优势:易于阅读、跨语言、通用性强。 不足:相对较慢,可能产生大量文本数据。

XML序列化:

优势:可读性强、结构化明确。 不足:相对冗长,性能较JSON差。

Protocol Buffers:

优势:高性能、紧凑、适用于跨系统通信。 不足:对数据结构定义要求严格,不够直观。

Kryo和Hessian:

优势:高性能、紧凑。 不足:可能不适用于所有数据类型,不如JSON、XML通用。

实现难度:

Serializable接口较为简单,JSON和XML相对易于理解。Protocol Buffers需要定义数据结构,较为复杂。Kryo和Hessian使用相对复杂但更高效的序列化方式。

跨系统和跨语言:

Serializable接口在Java环境下通用,但不适用于跨语言。JSON、XML和Protocol Buffers能够实现跨系统、跨语言交互。Kryo和Hessian则取决于具体的实现和库。

性能:

Serializable接口性能较低,JSON和XML相对较慢。Protocol Buffers、Kryo和Hessian具有更高的性能,尤其适用于高性能需求和大规模数据传输。

四.通常使用哪一个呢?。

在java的本系统中

没有特殊的要求下Serializable就可以了,因为简单。

注意事项:

1.序列化ID(Serial Version UID):确保显式声明serialVersionUID,这是序列化的版本标识符。它保证了反序列化时的兼容性。如果不显式指定,每次编译类时都会自动生成,可能导致兼容性问题。

serialVersionUID,该字段必须是静态的、final的和 long 类型;例如:访问修饰符 static final long serialVersionUID = 42L;

2.静态变量不能序列化(static修饰的属性)

3.不需要序列化使用transient关键字

4.序列化的类serialVersionUID要保持一致,避免序列化失败抛出InvalidClassExceptio异常

涉及到不同系统或与移动端交互

一般Json比较合适,因为可读性强,开发中遇到数据交互问题容易发现。


全部评论: 0

    我有话说:

    java高频面试-Spring中Bean的生命周期

    Spring中Bean的生命周期有如下过程: 1.Bean容器找到配置文件中Spring Bean的定义。 2.Bean容器利用Java Reflection API创建一个Bean的实例。 3

    java高频面试-java类加载需要经历哪些过程?

    本篇文章是基于JDK 8及以上版本的Java类加载过程。 Java类加载过程 Java类加载是Java虚拟机(JVM)执行过程中的关键步骤。它涉及Java类的动态加载、链接初始化。在本文中,我们将

    java高频面试-mysql的InnoDB与MyISAM存储引擎有哪些区别 ?

    mysql的InnoDB与MyISAM存储引擎有哪些区别 ? MySQL是一个广泛使用的关系型数据库管理系统,其中InnoDBMyISAM是两种常用的存储引擎。它们在功能性能方面存在着显著的差异

    java高频面试-线程池中execute跟submit的区别?

    ``当谈论线程池时,其中的executesubmit是两种常用的方法,它们在任务提交执行上有所不同。 线程池中 execute 与 submit 方法的区别 1.execute 方法

    java高频面试-在Spring中,当一个Bean依赖另一个Bean时,如果这两个Bean之间出现了循环依赖,Spring会如何处理呢?

    Spring 中的循环依赖处理 循环依赖是指两个或多个Bean之间相互依赖,形成了相互引用的关系。在Spring框架中,如果遇到循环依赖,即两个Bean互相持有对方的引用,Spring框架如何处理呢

    我向20k+以上的java高级开发工程师提了那些面试问题

    公司需要一位java高级开发工程师,找到我去面试。我回忆了一下,记录部分我的提问,如果大家刚兴趣可以给我留言,我视情况看是否继续补充,或者是否提供答案。 1.聊聊您对spring Boot一些见解

    Java如何返回多个值

      我有一个方法,需要返回多个对象。可是Java只能返回一个值,请问如何才能返回多个值呢?

    Java 平台标准版文档

    您在台式机服务器上开发部署 Java 应用程...

    spring boot面试及答案持续更新中

    2019-07-28最新整理的spring boot面试及答案 1.Spring Boot是什么 这是摘自官方的一段话 Spring Boot is designed to get you up

    java程序员必须知道的网站

    sping官网 spring的各种框架给java开发带来的便利至今无法撼动 github 有各种语言的项目都有托管在上面,各种demo使用起来省心省力 stackoverflow 各种程序所遇到的

    java实现判断是手机端还是pc端访问, nginx实现判断是手机端还是pc端访问

    1.编写工具类 /** * @author 缘分哥 * @description 判断是否移动端工具 */ public class ClientUtils { public static String[] mobileAgents = { "i...

    今日摘抄:主动支配自己碎片时间方法

    这两天在看李尚龙的《你没有退路,才有出路》这本书。目前还没有看完,我一直很喜欢他的书。 他在文章中说:“自己不主动使用碎片时间,这些时间就会被别人利用”,的确是这样子的,里面他分享了主动支配自己

    SpringBoot系列19-防止重复请求,重复表单提交超级简单注解的实现之四(终极版II)

    前言: 根据最新spring boot:2.5.0版本在《SpringBoot防止重复请求,重复表单提交超级简单的注解实现之四(终极版I)》之上繁为简抽取更实用的代码,新增超时机制 防重复提交

    Caused by: java. io.I0Exception:The

    Caused by: java. io.I0Exception:The"/xxxx/xxx" 检查建议: 1. 确保服务器目录部署的服务是同一台机器 2. 确保此目录针对tomcat有访问

    加入公众号
    加入公众号