Java中的序列化方法探索

news2024/11/18 11:18:59

.为什么要序列化

对象不序列化,能直接存储吗?
在 Java 中,序列化是将对象的状态信息转换为可以存储或传输的形式(例如,转换为字节流)的过程。在对象数据需要在网络上传输或需要在磁盘上持久化存储时,序列化是必不可少的
对象在没有序列化的情况下不能直接存储在像文件系统或数据库这样的持久化存储中。序列化是将对象的状态转换为一种可以存储或传输的格式的过程。
没有序列化,对象是一个内存中的数据结构,不能直接存储到硬盘或通过网络传输。如果要持久化存储或在网络间传输一个对象,您需要先将其序列化为如二进制、JSON、XML 等格式。
这些格式可以被写入文件系统、数据库或通过网络发送,并在需要时反序列化回原始对象。

java中的序列化几种形式

Java 原生序列化:通过实现 java.io.Serializable 接口。对象被转换成二进制流以便于存储或传输。
JSON 序列化:使用库如 Jackson 或 Gson,将对象转换为 JSON 格式的字符串。
XML 序列化:使用如 JAXB (Java Architecture for XML Binding) 等库将对象转换为 XML 格式。
Google Protocol Buffers:一种语言和平台无关的高效二进制序列化库。
Apache Avro:支持丰富的数据结构的数据序列化系统。
Kryo:一个快速高效的 Java 二进制序列化和反序列化库。

以下以Serializable 和 JSON做分析

java 原生的序列化机制Serializable

在 Java 中,可以通过 原生的序列化机制。实现 java.io.Serializable 接口来启用对象的序列化。这个接口是一个标记接口,它不包含任何方法,仅标记类的对象可以被序列化。
版本兼容性:如果序列化的对象在不同版本之间发生变化,可能会遇到兼容性问题。为此,可以使用 serialVersionUID 来管理版本。
transient 关键字:如果您的类中有一些不需要序列化的字段(无论是 String 类型还是其他类型),可以使用 transient 关键字标记这些字段。
private int myInt; // 基本类型 int
在 Java 中,基本数据类型(如 int、double、boolean 等)本身并不实现 Serializable 接口,因为它们不是对象。但是,当基本数据类型被用作类的字段时,在该类实现了 Serializable 接口的情况下,这些基本数据类型的字段会自动包含在序列化过程中。
这意味着,如果您创建了一个实现了 Serializable 接口的类,并且这个类包含基本数据类型的字段,那么当您序列化这个类的对象时,这些基本数据类型的字段也会被序列
通常Serializable 序列化会有乱码
序列化过程生成的二进制数据不仅包含字符串的内容,还包含了 Java 对象序列化的附加信息,如类信息、序列化版本 ID 等。
这部分数据在文本编辑器中通常显示为乱码,因为它们包含非文本字符
Serializable序列化的的二进制,查看可以用二进制编辑器查看,不过可是不可识别的字符
(Notepad++ 安装插件 HEX-Editor 8.5.3Notepad++ 下载0.9.12 HEX-Editor)
在这里插入图片描述

测试 HashMap序列化与反序列化

package com.example.demo;

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.util.HashMap;

public class SerializeExample {
public static void main(String[] args) {
String str = “Hello, World!”; // 字符串对象
try {
// 创建一个指向文件的输出流
FileOutputStream fileOut = new FileOutputStream(“D:\file.bin”);
// 创建一个对象输出流,并将其包装在 fileOut 流中
ObjectOutputStream out = new ObjectOutputStream(fileOut);
HashMap<String, String> hashMap = new HashMap<>();
hashMap.put(“key”,“111”);
// 序列化字符串对象
out.writeObject(hashMap);

        // 关闭所有流
        out.close();
        fileOut.close();

        System.out.println("Serialized data is saved in string.ser");
    } catch (IOException i) {
        i.printStackTrace();
    }
}

}

package com.example.demo;

import java.io.FileInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.util.HashMap;

public class DeserializeExample {
public static void main(String[] args) {
HashMap<String,String> str = new HashMap();
try {
// 创建一个指向文件的输入流
FileInputStream fileIn = new FileInputStream(“D:\file.bin”);
// 创建一个对象输入流,并将其包装在 fileIn 流中
ObjectInputStream in = new ObjectInputStream(fileIn);

        // 反序列化字符串对象  反序列化时使用 ObjectInputStream 读取序列化的对象数据,会返回一个 Object 类型的实例。如果您知道该对象的具体类型,通常需要进行显式的类型转换(强转)以恢复到其原始类型。
        str = (HashMap<String, String>) in.readObject();
        str.forEach((k,v)->{
            System.out.println(k+"        "+v);
        });

        // 关闭所有流
        in.close();
        fileIn.close();
        System.out.println("Deserialized String: " + str);
    } catch (IOException i) {
        i.printStackTrace();
        return;
    } catch (ClassNotFoundException c) {
        System.out.println("String class not found");
        c.printStackTrace();
        return;
    }
}

}

二:JSON序列化

JSON(JavaScript Object Notation)是一种轻量级的数据交换格式(一种格式)。JSON 使用文本格式来表示对象,使其网络上进行数据传输,被绝大多数编程语言解析。
普通文本对象打印为:对象信息,别人无法识别
package com.example.demo;

import com.alibaba.fastjson.JSON;
import java.io.FileWriter;
import java.io.IOException;

public class JsonToFileExample {

public static void main(String[] args) {
    // 创建要序列化的对象
    MyObject obj = new MyObject();
    obj.setName("Example Name");
    obj.setValue(123);

    // 使用 Fastjson 将对象转换为 JSON 字符串

// String jsonString = JSON.toJSONString(obj);

    // 将 JSON 字符串保存到文件
    try (FileWriter file = new FileWriter("D:\\object.txt")) {
        file.write(obj.toString());
        file.flush();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

static class MyObject {
    private String name;
    private int value;

    // getters 和 setters
    public String getName() {
        return name;
    }

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

    public int getValue() {
        return value;
    }

    public void setValue(int value) {
        this.value = value;
    }
}

}
在这里插入图片描述
如果转成json则可以打印为:
public class JsonToFileExample {

public static void main(String[] args) {
    // 创建要序列化的对象
    MyObject obj = new MyObject();
    obj.setName("Example Name");
    obj.setValue(123);

    // 使用 Fastjson 将对象转换为 JSON 字符串
    String jsonString = JSON.toJSONString(obj);

    // 将 JSON 字符串保存到文件
    try (FileWriter file = new FileWriter("D:\\object.txt")) {
        file.write(jsonString);
        file.flush();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

static class MyObject {
    private String name;
    private int value;

    // getters 和 setters
    public String getName() {
        return name;
    }

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

    public int getValue() {
        return value;
    }

    public void setValue(int value) {
        this.value = value;
    }
}

在这里插入图片描述

在 Spring Boot 项目中,使用 Feign 进行远程调用时,对象的传输通常不依赖于 Java 的原生序列化机制(即实现 Serializable 接口)。
Feign 和其他 Spring Cloud 组件在进行远程调用时,会使用 HTTP 协议,并且通常结合了如 JSON 或 XML 等格式的 HTTP 消息转换器来序列化和反序列化对象。
当一个服务调用另一个服务时,Feign 客户端会将 Java 对象转换为 JSON(或其他格式),然后通过 HTTP 请求发送。接收方的服务会将这些 JSON 数据反序列化回 Java 对象。这个过程并不要求 Java 对象实现 Serializable 接口,因为它是基于 HTTP 和消息转换器(如 Jackson JSON 处理库),而不是 Java 原生的序列化机制。
JSON(JavaScript Object Notation)是一种轻量级的数据交换格式,它可以用于数据的传输和转换。JSON 在不同语言和平台之间传输数据时特别有用,因为它易于人阅读和编写,同时也易于机器解析和生成。在许多现代编程环境和网络应用中,JSON 被广泛用于前后端之间的数据传递,以及不同系统之间的数据交换。JSON 格式因其文本形式和自描述性,成为了 Web API 和微服务架构中常用的数据格式。
序列化不一定需要通过实现 Java 的 Serializable 接口来完成。将对象转换成 JSON、XML 或其他格式也是一种序列化的方法。这些方法允许您将对象的状态转换成一种可以存储或传输的格式,而不依赖于 Java 内置的序列化机制。JSON 和 XML 序列化的优点是它们更加灵活,并且与使用不同编程语言的系统之间的兼容性更好。
换成 JSONObject 通常不会携带有关对象原始类的详细信息,例如类名或属性的数据类型。JSONObject 主要是一种以键值对形式存储数据的结构,其中键通常是字符串,对应对象的字段名称,值是字段的值。这意味着对象的结构会被保留,但不包括其作为特定类实例的信息。当从 JSONObject 反序列化时,您需要知道要将其转换成哪种具体的类类型。虽然 JSON 序列化产生的是文本数据,但这些文本数据最终在存储或传输时仍然以二进制的形式存在(因为所有的文件和网络数据传输本质上都是二进制的)。
在 Spring Boot 应用中,当在 Controller 层将对象转换为 JSON 时,通常这是通过使用 Spring MVC 框架的内置功能自动完成的。这里是一个简单的例子:
@RestController 注解表明这个类是一个 Spring MVC Controller,并且所有的响应都会自动转换成 JSON。
ResponseEntity 用于包装响应对象,Spring MVC 会自动使用 Jackson 或其他配置的 JSON 转换库将 MyObject 实例转换成 JSON 格式。
当客户端请求 /myendpoint 时,方法 getMyObject() 会被调用,返回的 MyObject 对象将被自动序列化为 JSON。

在这段 Spring Boot 控制器代码中,序列化主要发生在将 Java 对象转换为 HTTP 响应的 JSON 数据时。这是由 Spring MVC 框架自动处理的。
Spring Boot 应用中,当您的控制器方法返回一个对象时,Spring MVC 使用配置的消息转换器(默认是 Jackson)将对象转换为 JSON 格式。这个过程与对象是否实现 Serializable 无关。
在 Spring MVC 框架中,对象到 JSON 的自动转换是由 HttpMessageConverter 接口的实现类处理的。具体来说:
MappingJackson2HttpMessageConverter:
这是最常用的转换器,用于处理 JSON 数据。它使用 Jackson 库将 Java 对象转换为 JSON,以及将 JSON 转换为 Java 对象。

配置:
在 Spring MVC 中,这些转换器通常是自动配置的。您可以通过配置 WebMvcConfigurer 来自定义这些转换器的行为。
当一个控制器方法返回对象时,Spring MVC 框架会使用合适的 HttpMessageConverter(如 MappingJackson2HttpMessageConverter)来将对象转换为相应格式的响应体(在大多数情况下是 JSON)。
在 Spring MVC 中,以下几个因素通常指示框架自动处理对象到 JSON 的转换:
@RestController 注解:这个注解表明类中的所有方法返回值都应被视为响应体,并且默认会转换为 JSON。
@ResponseBody 注解:在一个使用 @Controller 注解的类中,@ResponseBody 可以用于具体的方法上,表示该方法的返回结果应该被转换为响应体。
内容协商:Spring MVC 根据请求头(如 Accept)进行内容协商,确定使用哪种格式的响应。
配置的消息转换器:如果项目中配置了 MappingJackson2HttpMessageConverter(默认情况下是有的),它会自动用于转换 JSON。
返回类型:方法的返回类型通常是一个 POJO(普通的 Java 对象),Spring MVC 会尝试将其序列化为 JSON。

HTTP(超文本传输协议)可以传输多种类型的数据,包括但不限于:

文本数据:如 HTML 页面、JSON 或 XML 数据、普通文本等。
数字:作为文本的一部分传输,如查询参数或 JSON/XML 的一部分。
图像和多媒体:如 JPEG、PNG 图像,MP3 音频,MP4 视频等。
二进制数据:任何形式的文件数据,如文档、压缩文件等。
表单数据:通过表单提交的数据,包括文本字段、数字、文件上传等。
所以他可以传递string类型(普通文本) 数字,json等,但是不能传递java对象

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1352083.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Spring Boot学习随笔- 集成MyBatis-Plus(二)条件查询QueryWrapper、聚合函数的使用、Lambda条件查询

学习视频&#xff1a;【编程不良人】Mybatis-Plus整合SpringBoot实战教程,提高的你开发效率,后端人员必备! 查询方法详解 普通查询 // 根据主键id去查询单个结果的。 Test public void selectById() {User user userMapper.selectById(1739970502337392641L);System.out.print…

opencv期末练习题(3)附带解析

创建黑色画板&#xff0c;并支持两种画图功能 import mathimport cv2 import numpy as np """ 1. 创建一个黑色画板 2. 输入q退出 3. 输入m切换画图模式两种模式&#xff0c;画矩形和画圆形。用户按住鼠标左键到一个位置然后释放就可以画出对应的图像 "&qu…

Eureka学习思维导图

一、Eureka Server原理解析 参考&#xff1a;https://www.jianshu.com/p/eb690e6ab11d 二、Eureka Client源码解析 参考&#xff1a;https://www.jianshu.com/p/6e8850387da6

Threejs项目实战之四:实现地图雷达效果

目录 最终效果代码实现创建项目DigitalMapView.vue的核心代码 最终效果 最近事情比较多&#xff0c;今晚难得有空&#xff0c;就抽空完成了一个使用Threejs实现地图雷达扫描效果的程序&#xff0c;下面说下代码实现的原理及核心代码&#xff0c;老规矩&#xff0c;先看下效果图…

专业服务新篇章:ToB行业运营达人的能力与策略

又逢年底&#xff0c;这两天冷空气南袭&#xff0c;深圳的天气也转为湿冷&#xff0c;又到了年终总结复盘的时候了&#xff0c;其实这样的天气挺适合做深度的思考&#xff0c;清冷的空气&#xff0c;可以让人保持清醒。 月初市场同事希望我写点东西&#xff0c;题目内容自拟&a…

7-验证码识别

文章目录 验证码识别1、验证码的用途和分类验证码的作用验证身份验证行为 验证码的类型静态验证码&#xff1a;图片验证码问答式验证码问答式验证码行为式验证码&#xff1a;点击行为式验证码&#xff1a;拖动间接式验证码&#xff1a;短信、邮件、语音电话无感验证码 2、验证码…

2023年12月青少年软件编程Python等级考试(三级)真题试卷

2023年12月青少年软件编程Python等级考试&#xff08;三级&#xff09;真题试卷 题目总数&#xff1a;38 总分数&#xff1a;100 选择题 第 1 题 单选题 一个非零的二进制正整数&#xff0c;在其末尾添加两个“0”&#xff0c;则该新数将是原数的&#xff1f;&#x…

虹科方案丨从困境到突破:TigoLeap方案引领数据采集与优化变革

来源&#xff1a;虹科工业智能互联 虹科方案丨从困境到突破&#xff1a;TigoLeap方案引领数据采集与优化变革 原文链接&#xff1a;https://mp.weixin.qq.com/s/H3pd5G8coBvyTwASNS_CFA 欢迎关注虹科&#xff0c;为您提供最新资讯&#xff01; 导读 在数字化工厂和智能制造时…

mcu与上位机通讯数据传输测速

问题 如何测量mcu与上位机通讯数据传输速度&#xff1f;&#xff08;串口、USB&#xff09; 解决 可以借助Bus Hound 将显示时间戳勾上。 发送一段固定长度的数据&#xff0c;然后除起始和结束的时间差 最后计算即可。

xadmin-plus

python之Xadmin-plus是什么&#xff1f; xadmin-plus: xadmin的django3.2版本支持。 Xadmin是一个非常优秀的Django Admin插件&#xff0c;可惜的是已经停止更新。Xadmin-plus对其进行了升级兼容。支持python3.10、Django3.2。 特性 Django Admin直接替换基于Twitter Boots…

安装Keras用于影像分割

conda create -n tfkears2024 python3.9.18 activate tfkeras2024 pip install tensorflow-gpu2.9.0 pip install keras pip install scipy pip install ipykernel ipython python -m ipykernel install --name tfkears2024

深度生成模型之GAN基础 ->(个人学习记录笔记)

文章目录 深度生成模型之GAN基础生成对抗网络1. 生成对抗网络如何生成数据2. 生成对抗原理3. GAN的核心优化目标4. D的优化5. GAN的理想状态6. GAN的训练7. 梯度不稳定与模式崩塌(collapse mode)问题8. 梯度消失问题 深度生成模型之GAN基础 生成对抗网络 1. 生成对抗网络如何…

【华为机试】2023年真题B卷(python)-靠谱的车

一、题目 题目描述&#xff1a; 程序员小明打了一辆出租车去上班。出于职业敏感&#xff0c;他注意到这辆出租车的计费表有点问题&#xff0c;总是偏大。 出租车司机解释说他不喜欢数字4&#xff0c;所以改装了计费表&#xff0c;任何数字位置遇到数字4就直接跳过&#xff0c;其…

关于使用 @iconify/iconify图标库组件在vite中的使用

Iconify 是最通用的图标框架&#xff0c;将各种图标库的图标集中在这里的一个组件库&#xff0c;例如ant-design,element-ui等 网站地址如下 https://iconify.design/getting-started/ 使用过程如下 npm install iconify/iconify -S npm install vite-plugin-purge-icons icon…

【SpringBoot3】命令行运行jar包报错可能的一些原因

端口号冲突&#xff1a; 有其他的web程序在运行&#xff0c;占用了8080端口没有主清单属性&#xff1a; 在打包jar包前&#xff0c;没有加入打包的插件spring-boot-maven-plugin&#xff0c;参考1.SpringBoot入门的第一个完整小项目&#xff08;新手保姆版教会打包&#xff09;…

Dockerfile与DockerCompose

Docker的Image结构是怎样的&#xff1f; 镜像是将应用程序 及其需要的 系统函数库、环境、配置、依赖 打包而成。 镜像结构 入口&#xff08; Entrypoint &#xff09; 镜像运行入口&#xff0c;一般是程序启动的脚本和参数 层&#xff08; Layer &#xff09; 在BaseImage基…

Alibaba Cloud Linux镜像操作系统详解(全方位解析)

Alibaba Cloud Linux是基于龙蜥社区OpenAnolis龙蜥操作系统Anolis OS的阿里云发行版&#xff0c;针对阿里云服务器ECS做了大量深度优化&#xff0c;Alibaba Cloud Linux由阿里云官方免费提供长期支持和维护LTS&#xff0c;Alibaba Cloud Linux完全兼容CentOS/RHEL生态和操作方式…

Linux 进程(五) 调度与切换

概念准备 当一个进程放在cpu上运行时&#xff0c;是必须要把进程的代码跑完才会进行下一个进程吗&#xff1f;答案肯定是 不对。现在的操作系统都是基于时间片轮转执行的。 时间片&#xff08;timeslice&#xff09;又称为“量子&#xff08;quantum&#xff09;”或“处理器片…

设计模式之原型模式【创造者模式】

学习的最大理由是想摆脱平庸&#xff0c;早一天就多一份人生的精彩&#xff1b;迟一天就多一天平庸的困扰。各位小伙伴&#xff0c;如果您&#xff1a; 想系统/深入学习某技术知识点… 一个人摸索学习很难坚持&#xff0c;想组团高效学习… 想写博客但无从下手&#xff0c;急需…

数据库云平台新数科技完成B轮融资,打造全链路智能化数据库云平台

数据库云平台软件厂商「北京新数科技有限公司」&#xff08;以下简称「新数科技」&#xff09;已于2023年完成B1轮和B2轮融资&#xff0c;分别由渤海创富和彬复资本投资&#xff1b;义柏资本担任本轮融资独家财务顾问。 新数科技成立于2014年&#xff0c;当前产品矩阵包括数据库…