背景
我们在进行传输的时候 会有一些状态值,如Status为1代表删除,为0代表失败或者怎么样的。只传输一个)0或者1过去给第三方(此处不包括给前端),如果没有契约第三方会不认识你这个是什么意思,那我们在平时写业务逻辑的时候使用枚举很轻易就知道了什么状态什么值。所以我们在构建DTO对象的时候里面放一个枚举来表示。
首先在阿里的规范里是这样说的:
【强制】二方库里可以定义枚举类型,参数可以使用枚举类型,但是接口返回值不允许使用枚举类型或者包含枚举类型的 POJO 对象。
那到底为啥不能用呢?
枚举
首先我们得先思考一下枚举是否可以进行序列化,我们在把对象进行传输的时候需要将这个对象序列化为字节序列进行传输(在linux中一切皆文件,JVM虚拟机将对象变为字节给到内核通过传输协议进行打包传)枚举在进行编译后会生成一个相关的类,这个类,这个类继承了JavaAPI中的java.lang.Enum类。那么我们看看这个类,毫无疑问可以序列化。继承了Serializable接口。那么就肯定就是可以序列化了。
Enum实战序列化
1. 创建一个枚举类
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文件夹中,再进行反序列化,读取查看枚举的值
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); } }
执行结果:
但是在控制台输出的对象是枚举的命名,没有枚举中的值,这时为什么呢?
==
我用的是aliFastJson转还为JsonObject的我们看看他里面的实现。只是拿了对应枚举的name(感觉是个坑啊),这也阿里规范中不能使用枚举放在DTO的原因之一吧==
上面的内容整明了枚举是可以进行序列化的,是可以被传输的,他的实现也是通过类来实现的,除了fastJSON那一步,使用都没有问题的。其他角度考虑
借鉴知乎
使用枚举的确会带来扩展兼容性的问题,这点很多答主都说的很好了,我就说一下为什么参数上可以使用枚举的原因吧。咱们先假定对枚举的扩展只是新增值,而不是减少值。比如说性别中本来是男和女,现在要增加一个transgender, 但我们极少极少会有需求说,把性别中的已有男或者女去掉。(我觉得这个假设是参数可以使用枚举型的前提)在这个假定下如果我们在接口中使用枚举型,如孤尽兄在java开发手册中所述,分为参数和返回值两种情况。不管是微服务之间的互相调用,还是手机客户端到服务器的调用,在不停机的情况下,服务器端和客户端是很难一起更新的,往往我们是服务器端先来支持新feature,然后再来逐步更新客户端。我想孤尽兄说参数可以使用枚举型,也是基于这种更新升级方式。因为服务器端如果突然开始返回transgender这个新性别,客户端吃不进去(反序列化不了),客户端就炸了。但如果服务器端只是在参数上开始接受新性别,那就不怕老客户端,反正老客户端还在那里继续发送男和女这两种性别,服务器端都认识,就不会出错。两边可以一直相安无事,慢慢等所有客户端都升级。但是呢,如果我们用string来代替枚举,服务器端贸然返回一个新的值,客户端不知道怎么处理,也可能会产生其他问题,比如说钱算错了之类业务层面的问题。所以客户端代码可能要先更新一点,让其能处理这个新的值。我觉得阿里把这个标准放在手册里,也是多年的经验教训,两害相权取其轻吧。因为很多应用是没法强制客户端一起更新的。尤其是手机移动客户端,ios可能还要审核,很难做到客户端和服务器端同步更新。如果是微服务,也很难在不停机的情况下,把通过枚举耦合两个微服务一起更新。
看完大佬的说法个人感觉:
是的你在一个项目中维护是没有什么问题。但是多个项目使用同一个枚举怎么搞。要么这个枚举一处动即全动。所有的项目使用这一个枚举。比如说全公司有一个通用的发票类型枚举,有几个状态值代表一钟发票类型,于是这个枚举维护到公共配置上,通过动态加载技术,在每次发布或者有修改的时候进行动态加载。感觉同完美。小白的YY。落地难吗??试一试。后面更新。
到此这篇关于浅谈Java中是否直接可以使用enum进行传输的文章就介绍到这了,更多相关Java enum 传输内容请搜索小牛知识库以前的文章或继续浏览下面的相关文章希望大家以后多多支持小牛知识库!
问题内容: 我不想使用jQuery,但我想使用Ajax进行文件上传。那可能吗? 如果是这样,我在哪里可以找到有关信息/教程? 问题答案: 不,无法使用javascript执行此操作。 但是,为了给人“ AJAX”的感觉,您可以向隐藏的iframe提交表单,然后将脚本结果输出到其中,然后从那里进行处理。Google 并从那里开始。 如果您使用的是jQuery,并且您的表单中包含任何文件字段,也可以使
问题内容: 我有3个屏幕,可以说, 登录 忘记密码 帮助画面 默认情况下,启动应用程序时将打开“登录”屏幕。单击“忘记密码”按钮时,将显示“忘记密码”屏幕,并且在单击“帮助”链接时将打开“帮助”屏幕。 我可以通过某种方式直接打开“忘记密码”屏幕,而无需执行使用 XCUITest 单击按钮的过程吗? 我建议与通过adb直接打开View的意图相同的内容。 问题答案: 据我所知,您不能使用XCUITes
我有int的向量,我需要找到并用特定的值替换一些元素。他们都是一样的 例如:将所有元素的4替换为8。 我正在尝试c中循环中的直接内存访问。但对我来说还是很慢。 更新: 我正在上使用OpenCV对象: 函数仅在释放模式下通过指针返回值
问题内容: 我是C ++中静态元编程的迷。我知道Java现在有了泛型。这是否意味着在Java中可以进行静态元编程(即,编译时程序执行)?如果是这样,任何人都可以推荐任何好的资源,以便在其中可以了解更多的信息? 问题答案: 这个问题已经有10多年的历史了,但是我仍然缺少一个答案。这是: 是的 ,但不是 因为 泛型,并且注释与C ++完全相同。 从Java 6开始,我们具有可插入注释处理api。静态元
问题内容: 我可以在Java中使用Scala List,例如: 它似乎没有编译。找不到List $ .apply方法。 当我将其更改为 其中Dir是我的scala类,而ls()返回一个scala列表,编译器抱怨 “内部编译器错误:java.lang.ClassCastException:org.eclipse.jdt.internal.compiler.lookup.BaseTypeBinding
问题内容: 我知道Java Webstart在安全的沙箱下运行。是否可以在jar中包含.dll / .exe(或让Webstart将其下载到本地计算机)然后执行(使用Runtime.exec或进程等) 请指教。任何建议/评论都欢迎! 问题答案: 是。您必须将包裹在一个文件中,然后使用 请参阅此处以获得更详细的描述。 如果要运行可执行文件,那么最好的选择是将其打包为资源,分解为(例如)一个临时目录,