Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >Java中是否直接可以使用enum进行传输

Java中是否直接可以使用enum进行传输

作者头像
袁新栋-jeff.yuan
发布于 2020-08-26 06:46:00
发布于 2020-08-26 06:46:00
4K00
代码可运行
举报
运行总次数:0
代码可运行

背景

我们在进行传输的时候 会有一些状态值,如Status为1代表删除,为0代表失败或者怎么样的。只传输一个)0或者1过去给第三方(此处不包括给前端),如果没有契约第三方会不认识你这个是什么意思,那我们在平时写业务逻辑的时候使用枚举很轻易就知道了什么状态什么值。所以我们在构建DTO对象的时候里面放一个枚举来表示。

首先在阿里的规范里是这样说的: 【强制】二方库里可以定义枚举类型,参数可以使用枚举类型,但是接口返回值不允许使用枚举类型或者包含枚举类型的 POJO 对象。 那到底为啥不能用呢?

枚举

  1. 首先我们得先思考一下枚举是否可以进行序列化,我们在把对象进行传输的时候需要将这个对象序列化为字节序列进行传输(在linux中一切皆文件,JVM虚拟机将对象变为字节给到内核通过传输协议进行打包传)枚举在进行编译后会生成一个相关的类,这个类,这个类继承了JavaAPI中的java.lang.Enum类。那么我们看看这个类,毫无疑问可以序列化。继承了Serializable接口。那么就肯定就是可以序列化了。

Enum实战序列化

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
1. 创建一个枚举类
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
package SerializableEnum;

/**
 * @Author:yuanxindong
 * @Date:2020/5/101:33
 */
public enum PersonEnum {
    /**
     * 小圆
     */
    YUANXINDONG("yuanxindong",1);

    ;
    private String age;
    private int i;

    PersonEnum(String yuanxindong, int i) {
        this.age = yuanxindong;
        this.i = i;
    }}

2.将枚举类放入Person对象,通过本地序列化存入target文件夹中,再进行反序列化,读取查看枚举的值

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
package SerializableEnum;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;

/**
 * @Author:yuanxindong
 * @Date:2020/5/101:31
 */
public class Person implements Serializable {
    private String name;
    PersonEnum a;

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

    public void setA(PersonEnum a) {
        this.a = a;
    }

    public String getName() {
        return name;
    }

    public PersonEnum getA() {
        return a;
    }

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", a=" + a +
                '}';
    }

    public static void main(String[] args) throws IOException, ClassNotFoundException {
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("object.txt"));
        Person p = new Person();
        p.setA(PersonEnum.YUANXINDONG);
        p.setName("小圆");
        oos.writeObject(p);

        ObjectInputStream ois = new ObjectInputStream(new FileInputStream("D:\\workCode\\票税助手\\aresV3\\springCodestudy\\object.txt"));
        Person brady = (Person) ois.readObject();
        brady.getA();

        System.out.println(brady);
    }
}
  1. 执行结果:

但是在控制台输出的对象是枚举的命名,没有枚举中的值,这时为什么呢?

== 我用的是aliFastJson转还为JsonObject的我们看看他里面的实现。只是拿了对应枚举的name(感觉是个坑啊),这也阿里规范中不能使用枚举放在DTO的原因之一吧==

上面的内容整明了枚举是可以进行序列化的,是可以被传输的,他的实现也是通过类来实现的,除了fastJSON那一步,使用都没有问题的。

其他角度考虑

借鉴知乎

使用枚举的确会带来扩展兼容性的问题,这点很多答主都说的很好了,我就说一下为什么参数上可以使用枚举的原因吧。咱们先假定对枚举的扩展只是新增值,而不是减少值。比如说性别中本来是男和女,现在要增加一个transgender, 但我们极少极少会有需求说,把性别中的已有男或者女去掉。(我觉得这个假设是参数可以使用枚举型的前提)在这个假定下如果我们在接口中使用枚举型,如孤尽兄在java开发手册中所述,分为参数和返回值两种情况。不管是微服务之间的互相调用,还是手机客户端到服务器的调用,在不停机的情况下,服务器端和客户端是很难一起更新的,往往我们是服务器端先来支持新feature,然后再来逐步更新客户端。我想孤尽兄说参数可以使用枚举型,也是基于这种更新升级方式。因为服务器端如果突然开始返回transgender这个新性别,客户端吃不进去(反序列化不了),客户端就炸了。但如果服务器端只是在参数上开始接受新性别,那就不怕老客户端,反正老客户端还在那里继续发送男和女这两种性别,服务器端都认识,就不会出错。两边可以一直相安无事,慢慢等所有客户端都升级。但是呢,如果我们用string来代替枚举,服务器端贸然返回一个新的值,客户端不知道怎么处理,也可能会产生其他问题,比如说钱算错了之类业务层面的问题。所以客户端代码可能要先更新一点,让其能处理这个新的值。我觉得阿里把这个标准放在手册里,也是多年的经验教训,两害相权取其轻吧。因为很多应用是没法强制客户端一起更新的。尤其是手机移动客户端,ios可能还要审核,很难做到客户端和服务器端同步更新。如果是微服务,也很难在不停机的情况下,把通过枚举耦合两个微服务一起更新。

看完大佬的说法个人感觉:

是的你在一个项目中维护是没有什么问题。但是多个项目使用同一个枚举怎么搞。要么这个枚举一处动即全动。所有的项目使用这一个枚举。比如说全公司有一个通用的发票类型枚举,有几个状态值代表一钟发票类型,于是这个枚举维护到公共配置上,通过动态加载技术,在每次发布或者有修改的时候进行动态加载。感觉同完美。小白的YY。落地难吗??试一试。后面更新。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2020/05/10 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
Enum源码解析
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
suveng
2019/09/18
1.2K0
Enum源码解析
3分钟快速阅读-《Effective Java》(七)
61.抛出与抽象相对应的异常 总而言之,如果不能阻止或者处理来自更底层的异常,一般的做法就是进行异常转译,异常转译就是高层捕获底层异常进行处理,或者把它转化层高层相同业务逻辑的异常. 62.每个方法抛出的异常都要有文档 简单来说对于异常可能出现的情况进行尽可能的声明,这样让调用你的人才能知道要怎么来使用对应的方法 63.在细节消息中包含能捕获失败的信息 简单来说,对于可能出现业务逻辑异常处应当做好对应的日志记录,这样才能更好的跟踪有些我们无法预料捕获而是由程序帮我们抛出的异常信息 64.
cwl_java
2019/10/26
3670
简述java序列化
1. 什么是Java对象序列化 Java平台允许我们在内存中创建可复用的Java对象,但一般情况下,只有当JVM处于运行时,这些对象才可能存在,即,这些对象的生命周期不会比JVM的生命周期更长。但在现实应用中,就可能要求在JVM停止运行之后能够保存(持久化)指定的对象,并在将来重新读取被保存的对象。Java对象序列化就能够帮助我们实现该功能。 使用Java对象序列化,在保存对象时,会把其状态保存为一组字节,在未来,再将这些字节组装成对象。必须注意地是,对象序列化保存的是对象的"状态",即它的成员变量。由此可知,对象序列化不会关注类中的静态变量。 除了在持久化对象时会用到对象序列化之外,当使用RMI(远程方法调用),或在网络中传递对象时,都会用到对象序列化。Java序列化API为处理对象序列化提供了一个标准机制,该API简单易用,在本文的后续章节中将会陆续讲到。 2. 简单示例 在Java中,只要一个类实现了java.io.Serializable接口,那么它就可以被序列化。此处将创建一个可序列化的类Person,本文中的所有示例将围绕着该类或其修改版。 Gender类,是一个枚举类型,表示性别
WindWant
2020/09/11
4590
Java 序列化基础知识
序列化机制允许将实现序列化接口的Java对象转换为字节序列。这些字节序列化可以保存到磁盘上,通过网络传输,以达到恢复到原来的对象的目的。
王小明_HIT
2020/03/25
3270
java原型模式
原型模式是用于创建重复的对象,同时又能保证性能,通过复制现有实例来创建新的实例对象,无需知道类的信息。
码农王同学
2020/03/25
3030
Java序列化,看这篇就够了
Java序列化是指把Java对象转换为字节序列的过程,而Java反序列化是指把字节序列恢复为Java对象的过程:
说故事的五公子
2021/02/02
2.7K1
Java Review(三十六、IO)
Java 的 IO 通过 java.io 包下的类和接口来支持, 在 java.io 包下主要包括输入、 输出两种 10 流, 每种输入、 输出流又可分为字节流和字符流两大类。 其中字节流以字节为单位来处理输入、 输出操作, 而字符流则以字符来处理输入、 输出操作。
三分恶
2020/07/16
8910
为什么Bean类要序列化?
在Java编程中,我们经常需要使用Bean类来表示数据对象。而将Bean类进行序列化是一个非常重要的概念。下面将详细说明为什么需要对Bean类进行序列化,并提供具体的例子和方法。
GeekLiHua
2025/01/21
370
单例设计模式(java与node实现)
单例模式,是一种常用的软件设计模式。在它的核心结构中只包含一个被称为单例的特殊类。通过单例模式可以保证系统中,应用该模式的类一个类只有一个实例。即一个类只有一个对象实例
许喜朝
2020/11/26
6410
设计模式【1.2】-- 枚举式单例有那么好用么?
单例模式:是一种创建型设计模式,目的是保证全局一个类只有一个实例对象,分为懒汉式和饿汉式。所谓懒汉式,类似于懒加载,需要的时候才会触发初始化实例对象。而饿汉式正好相反,项目启动,类加载的时候,就会创建初始化单例对象。
秦怀杂货店
2020/12/26
5190
Java基础之序列化对象Serialized
对于一般的类型都会实现该Serialized接口,例如:String、Data所以我们可以直接用。
全栈程序员站长
2022/09/12
4210
java序列化学习笔记
概念 序列化是将对象状态转换为可保持或传输的格式的过程。与序列化相对的是反序列化,它将流转换为对象。 这两个过程结合起来,可以轻松地存储和传输数据。以后,可以通过从存储区中读取或反序列化对象的状态,重新创建该对象。 目的 1、以某种存储形式使自定义对象持久化,在MVC模式中很是有用; 2、将对象从一个地方传递到另一个地方; 实现方法 实现 java.io.Serializable 接口 序列化时,需要用到对象输出流ObjectOutputStream ,然后通过文件输出流构造 ObjectOutputStr
张俊怡
2018/04/24
8420
Java基础18:Java序列化与反序列化
本文介绍了Java序列化的基本概念,序列化和反序列化的使用方法,以及实现原理等,比较全面地总结序列化相关知识点,并且使用具体例子来加以佐证。
程序员黄小斜
2019/04/07
1.1K0
Java IO详解(六)------序列化与反序列化(对象流)
该文讲述了序列化和反序列化在Java中的重要性,以及如何进行序列化和反序列化操作。序列化是将Java对象转换为字节流,以便在网络上传输或者持久化到磁盘。反序列化则是将字节流转换回Java对象。在序列化过程中,需要设置序列化版本,以确保反序列化时能够正确解析对象。同时,该文还介绍了如何通过ObjectOutputStream和ObjectInputStream进行对象序列化和反序列化操作,并给出了具体的示例代码。
IT可乐
2018/01/04
1.3K0
Java IO详解(六)------序列化与反序列化(对象流)
Java--Enum的思考
枚举类是Java5引进的特性,其目的是替换int枚举模式或者String枚举模式,使得语义更加清晰,另外也解决了行为和枚举绑定的问题.
屈定
2018/09/27
9950
java 的序列化和反序列化的问题
引言 将 Java 对象序列化为二进制文件的 Java 序列化技术是 Java 系列技术中一个较为重要的技术点,在大部分情况下,开发人员只需要了解被序列化的类需要实现 Serializable 接口,使用 ObjectInputStream 和 ObjectOutputStream 进行对象的读写。然而在有些情况下,光知道这些还远远不够,文章列举了笔者遇到的一些真实情境,它们与 Java 序列化相关,通过分析情境出现的原因,使读者轻松牢记 Java 序列化中的一些高级认识。 回页首 文章结构 本文
xiangzhihong
2018/01/30
9350
java 的序列化和反序列化的问题
详解设计模式:原型模式
原型模式(Prototype Pattern) ,是 GoF 的 23 种设计模式的一种,是用于创建重复的对象,同时又能保证性能。属于创建型模式,提供创建对象的最佳方式。
栗筝i
2022/12/02
4470
JAVA入门学习九
描述:序列流可以把多个字节输入流整合成一个, 从序列流中读取数据时将从被整合的第一个流开始读, 读完一个之后继续读第二个以此类推。 原因:由于多个输入流写入到一个输出流,代码重复性高则采用序列流进行输出; 基础语法:
全栈工程师修炼指南
2020/10/23
3940
设计模式 | 单例模式及典型应用
单例是最常见的设计模式之一,实现的方式非常多,同时需要注意的问题也非常多。要内容:
小旋锋
2019/01/21
1K0
dubbo服务接口设计的几个建议
那如何解决呢?其实很简单。服务接口的参数类型最好是封装类,增加参数的话只是在这个类增加一个字段。示例如下:
用户7634691
2020/08/10
2K0
相关推荐
Enum源码解析
更多 >
领券
💥开发者 MCP广场重磅上线!
精选全网热门MCP server,让你的AI更好用 🚀
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验