在阅读《阿里巴巴Java开发手册》时,发现有一条关于二方库依赖中接口返回值不允许使用枚举类型的规约,具体内容如下:

在谈论为什么之前先来科普下什么是二方库,二方库也称作二方包,一般指公司内部发布到中央仓库,可供公司内部其他应用依赖的库(jar 包)。

那么一方库便是本工程内部子项目模块依赖的库;三方库为公司之外的开源库,比如像 fastjson、easyexcel 这种。

下面我们就通过一个例子来看下为什么阿里巴巴不允许返回枚举类型或者包含枚举类型的 POJO 对象。

比如星巴克提供了 0.0.1 版本的二方库,定义了一个 Starbucks 类,里面包含了枚举类型的 SizeEnum,里面分别是中杯、大杯、特大杯。

public class Starbucks implements Serializable {
private Long id;
private String name;
private Integer capacity;
private SizeEnum sizeEum;
} public enum SizeEnum {
TALL(1),
GRANDE(2),
VENTI(3)
}

定义了一个服务类,实现了根据 id 获取星巴克的方法:

public class StarbucksImpl implements StarbucksService {
public Starbucks getStarbucksById(Long id) {
Starbucks starbucks = new Starbucks();
starbucks.setId(1L);
starbucks.setName("Latte");
starbucks.setCapacity(360);
starbucks.setSizeEnum(SizeEnum.TALL);
return starbucks;
}
}

然后,星巴克的门店引入 0.0.1 这个版本 jar 包,然后卖的好好的:

public class StarbucksDemo {
@Resource
private StarbucksService starbucksService; public void getStarbucks() {
Starbucks starbucks = starbucksService.getStarbucksById(1L);
System.out.println(starbucks);
}
}

有一天,老罗说要那个中等大小的中杯拿铁,但是服务员说那是大杯,经过一番争论,罗老师很是生气。

于是星巴克升级到了 0.0.2 版本二方库,在枚举类 SizeEnum 中新增了小杯,升级后的枚举类如下:

public enum SizeEnum {
TALL(1),
GRANDE(2),
VENTI(3),
SHORT(4)
}

同时服务类的接口方法也做了相应修改:

public class StarbucksImpl implements StarbucksService {
public Starbucks getStarbucksById(Long id) {
Starbucks starbucks = new Starbucks();
starbucks.setId(1L);
starbucks.setName("Latte");
starbucks.setCapacity(240);
starbucks.setSizeEnum(SizeEnum.SHORT);
return starbucks;
}
}

由于星巴克的门店比较多,有的还不知道这个新加的需求,因此返回结果中出现了 SHORT,但是 0.0.1 版本的二方库中没有小杯啊,所以就出问题了,也就是序列化失败。

通过这个例子,我相信大家对枚举类型作为返回结果有了一定的理解,下面引用孤尽大佬在知乎的回答:

由于升级原因,导致双方的枚举类不尽相同,在接口解析,类反序列化时出现异常。

Java 中出现的任何元素,在 Gosling 的角度都会有背后的思考和逻辑(尽管并非绝对完美,但 Java 的顶层抽象已经是天才级了),比如:接口、抽象类、注解、和本文提到的枚举。枚举有好处,类型安全,清晰直接,还可以使用等号来判断,也可以用在 switch 中。它的劣势也是明显的,就是不要扩展。可是为什么在返回值和参数进行了区分呢,如果不兼容,那么两个都有问题,怎么允许参数可以有枚举。当时的考虑,如果参数也不能用,那么枚举几乎无用武之地了。参数输出,毕竟是本地决定的,你本地有的,传送过去,向前兼容是不会有问题的。但如果是接口返回,就比较恶心了,因为解析回来的这个枚举值,可能本地还没有,这时就会抛出序列化异常。

比如:你的本地枚举类,有一个天气 Enum:SUNNY, RAINY, CLOUDY,如果根据天气计算心情的方法:guess(WeatcherEnum xx),传入这三个值都是可以的。返回值:Weather guess(参数),那么对方运算后,返回一个 SNOWY,本地枚举里没有这个值,傻眼了。

总结

本文通过一个实例让大家理解到枚举类型作为返回结果的坑,大家可以使用基本类型或者基本类型包装类来替换掉枚举类型就可以避免掉这么问题了。

大家对于这条规约​有什么看法,也欢迎留言讨论。​

最好的关系就是互相成就,大家的在看、转发、留言三连就是我创作的最大动力。

参考

《Java开发手册》泰山版

https://www.zhihu.com/question/52760637/answer/338584321

为什么阿里巴巴Java开发手册中强制要求接口返回值不允许使用枚举?的更多相关文章

  1. 为什么阿里巴巴Java开发手册中强制要求整型包装类对象值用 equals 方法比较?

    在阅读<阿里巴巴Java开发手册>时,发现有一条关于整型包装类对象之间值比较的规约,具体内容如下: 这条建议非常值得大家关注, 而且该问题在 Java 面试中十分常见. 还需要思考以下几个 ...

  2. 为什么阿里巴巴Java开发手册中强制要求不要在foreach循环里进行元素的remove和add操作?

    在阅读<阿里巴巴Java开发手册>时,发现有一条关于在 foreach 循环里进行元素的 remove/add 操作的规约,具体内容如下: 错误演示 我们首先在 IDEA 中编写一个在 f ...

  3. 为什么阿里巴巴Java开发手册中不建议在循环体中使用+进行字符串拼接?

    之前在阅读<阿里巴巴Java开发手册>时,发现有一条是关于循环体中字符串拼接的建议,具体内容如下: 那么我们首先来用例子来看看在循环体中用 + 或者用 StringBuilder 进行字符 ...

  4. 为什么阿里巴巴Java开发手册中不允许魔法值出现在代码中?

    在阅读<阿里巴巴Java开发手册>时,发现有一条关于关于常量定义的规约,具体内容如下: 图中的反例是将数据缓存起来,并使用魔法值加链路 id 组成 key,这就可能会出现其他开发人员在复制 ...

  5. 阿里巴巴Java开发手册中的DO、DTO、BO、AO、VO、POJO定义

    分层领域模型规约: DO( Data Object):与数据库表结构一一对应,通过DAO层向上传输数据源对象. DTO( Data Transfer Object):数据传输对象,Service或Ma ...

  6. 《阿里巴巴Java开发手册》代码格式部分应用——idea中checkstyle的使用教程

    <阿里巴巴Java开发手册>代码格式部分应用--idea中checkstyle的使用教程 1.<阿里巴巴Java开发手册> 这是阿里巴巴工程师送给各位软件工程师的宝典,就像开车 ...

  7. 为什么阿里巴巴开发手册中强制要求 POJO 类使用包装类型?NPE问题防范

    封面:学校内的秋天 背景:写这个的原因,也是我这两天凑巧看到的,虽然我一直有 alibaba Java 开发手册,也看过不少次,但是一直没有注意过这个问题 属于那种看过,但又没完全看过 一起来看看吧冲 ...

  8. 阿里巴巴Java开发手册———个人追加的见解和补充(一)

    先上干货,<阿里巴巴Java开发手册>的下载地址 https://yq.aliyun.com/articles/69327?spm=5176.100239.blogcont69327.15 ...

  9. 阿里巴巴Java开发手册评述

    2016年底的时候阿里巴巴公开了其在内部使用的Java编程规范.随后进行了几次版本修订,目前的版本为v1.0.2版.下载地址可以在其官方社区-云栖社区https://yq.aliyun.com/art ...

随机推荐

  1. 关于 Blob

    博客地址:https://ainyi.com/88 对于 Blob,前端开发中可能比较少遇到:数据库中可使用 Blob 概念,例如 Mysql 存储二进制数据的类型就是 Blob,也就是说图片可存储于 ...

  2. Linux常用命令~新手必知

    ifconfig查看本机IP ls  查看当前目录下所有文件及文件夹 ll      以详细方式显示所有文件与文件夹.(相当于 ls -l 命令) pwd     显示当前目录路径 cd  /user ...

  3. lodash入门

    简介 Lodash是一个著名的javascript原生库,不需要引入其他第三方依赖.是一个意在提高开发者效率,提高JS原生方法性能的JS库.简单的说就是,很多方法lodash已经帮你写好了,直接调用就 ...

  4. 「雕爷学编程」Arduino动手做(17)---人体感应模块

    37款传感器和模块的提法,在网络上广泛流传,其实Arduino能够兼容的传感器模块肯定是不止37种的.鉴于本人手头积累了一些传感器与模块,依照实践出真知(动手试试)的理念,以学习和交流为目的,这里准备 ...

  5. 读懂这几个关键词,你就能了解 Docker 啦

    基于高度虚拟化所诞生的容器技术,如今已经走向大规模应用.那么容器.虚拟机.Docker.Openstack.Kubernetes 之间又有什么关系,对现在的选择有什么影响呢? 上世纪 60 年代,计算 ...

  6. Aangular 父子间组件传递

    1.父子间组件传递------重点&难点 Vue.js和Angular中的父子间消息传递原理一样,都可以用口诀: “Props Down,Events Up” 方向1:父 =>子 父组件 ...

  7. shipyard的安装与一般维护

    #一.安装前的准备: docker pull alpine docker pull library/rethinkdb docker pull microbox/etcd docker pull sh ...

  8. Apache Module mod_reqtimeout

    Apache Module mod_reqtimeout Available Languages: en Description: Set timeout and minimum data rate ...

  9. 【c#】Visual Studio 的下载及安装

    “工欲善其事,必先利其器” 这篇博文我们介绍一下如何正确的安装基于c#使用的vs 2017. 1.首先在官网下载Visual Studio,下载地址:https://www.visualstudio. ...

  10. Java——Json字符串与Object互转

    public static void JacksonTest() {//推荐 //{"MNG001":[{"ID":"1","PW ...