引言
在这一周的工作中
碰到一个业务场景,须要叫旁边的共事,李同学开了一个接口,发现给我的返回值中带了枚举类型的变量,我顺口提了一嘴,这种接口返回值最好不要用这种蕴含枚举类型的对象
李同学问我为什么,我就间接说了,在《Java开发手册》中强制规定二方库里能够定义枚举类型,参数能够应用枚举类型,然而接口返回值不容许应用枚举类型或者蕴含枚举类型的 POJO 对象
然而,预先想了一想,孤尽老师在《手册》中写的的这条规定肯定正确吗?
注释
杨小帅:不懂同学,你这个接口咋回事,序列化异样了?
<img src="https://gitee.com/isysc/image-bed/raw/master/image-20210808153018319.png" alt="image-20210808153018319" style="zoom: 50%;" />
不懂只管心里慌的一批,然而外表依然装作稳得一笔:不是吧,必定是你调用的形式有误、你本人在回去查看查看、我都没动这个接口
不懂自信的三连击,让小帅纳闷的回到了座位
此时,不懂连忙关上 idea “我就改了一个接口的枚举值,咋会反序列化异样,不对,我记得手册中讲过 接口返回值不容许应用枚举类型或者蕴含枚举类型的 POJO 对象,完蛋完蛋,写代码的时候咋遗记了呢,让我快改回去,只有我改的够快,就没人发现我的 bug“
此时杨小帅曾经悄悄的站在不懂的工位后,看见了不懂在改枚举,“不懂就是你,这个标准你都能遗记,你咋回事”
不懂略显羞涩的笑了一下:“失误,失误,可控,可控”
杨小帅:“像这种二方库接口返回值记得多操个心”
此时小美凑了过去:“啥是二方库?”
杨小帅甩了甩头发:二方库也称作二方包,个别指公司外部公布到地方仓库,可供公司外部其余利用依赖的库(jar 包);一方库是本工程外部子项目模块依赖的库;三方库为公司之外的开源库,比方像 fastjson、easyexcel 这种
小美:为啥这种接口返回值不容许应用枚举类型或者蕴含枚举类型的 POJO 对象?
杨小帅:是这样的,不懂改了枚举,就导致咱们单方的枚举不同,在接口解析中就呈现了,反序列化时出现异常
比方:你的本地枚举类,有一个天气 Enum:SUNNY, RAINY, CLOUDY,如果依据天气计算情绪的办法:guess(WeatcherEnum xx),传入这三个值都是能够的
返回值为 Weather guess(参数),那么对方运算后,返回一个 SNOWY,本地枚举里没有这个值,就异样了
小美点了拍板,原来是这样啊
此时,王经理走了过去,向大家问到:这条标准肯定适合吗?
小美:我感觉小帅说的很有情理啊,接口返回值应用枚举确实会造成这样的异样呀
王经理:大家感觉枚举存在的意义是什么?
不懂:这题我会,就是顾名思义,见到就是晓得这个字段是什么意思,不像 String 类型,假如传个1、2、3,不晓得传的啥意思
王经理:说的有情理,枚举,就是把已知的全副列举进去。作为二方/三方库的提供者,我反对什么,你们就是用什么,这样是平安的。库版本升级后我反对了更多,你不晓得状况下天然不会应用,反正我不反对的参数你不可能传递给我,所以作为输出,枚举几乎就是平安保障,但作为返回值,状况就反过来了。我先通知你这些这些能够有,而后你规定这些这些能够有,除此之外都没有。然而,是我说了算而不是你,所以你的规定狗屁不是。提供者偷偷降级,抛异样的可能性直趋百分百
那咱们碰到,像不懂这样的坑货,偷偷降级怎么办,这个接口调用方少的能够告诉同步降级,那么,要是一个接口有百十个调用方呢,能够做到同步降级吗?
那么可不可以在咱们调用的时候,增强咱们框架的健壮性,如果发序列化时发现了新的枚举值,则这个字段设置为null,就像Apache Thrift代码外面写的那样?
王经理:好,明天就讲这些,你们思考思考
小美、不懂、小帅陷入了思考中.....
总结
其实呢
在二方库返回的接口中,如果该枚举的值是必须应用到枚举外部定义的办法和属性的,那么配置无奈转换时就报错的策略
如果该枚举在业务中能够只解决意识的枚举,不意识的枚举不进行解决的,就配置转换为null的策略
如果该枚举在业务中不意识时当作某个默认值解决,就配置转换为默认值的策略
如果该枚举在本地业务基本没有应用,并不关怀,那么能够在定义接管对象时间接定义为int或者String类型.
这样在整体序列化框架中进行自定义枚举类的转换对安全检查和扩展性的兼容性更加好,既能够兼容到枚举的益处,也能够强壮咱们的RPC框架,那么能在顶层做的事件,是不是能够改进下,让开发者更难受呢?
当然所有的出发点,还是基于咱们目前的一个业务场景和理论状况来的,应用的时候能够多多思考
附上孤尽老师对于这条规定的答复
因为降级起因,导致单方的枚举类不尽相同,在接口解析,类反序列化时出现异常。
Java 中呈现的任何元素,在 Gosling 的角度都会有背地的思考和逻辑(只管并非相对完满,但 Java 的顶层形象曾经是蠢才级了),比方:接口、抽象类、注解、和本文提到的枚举。枚举有益处,类型平安,清晰间接,还能够应用等号来判断,也能够用在 switch 中。它的劣势也是显著的,就是不要扩大。可是为什么在返回值和参数进行了辨别呢,如果不兼容,那么两个都有问题,怎么容许参数能够有枚举。过后的思考,如果参数也不能用,那么枚举简直无用武之地了。参数输入,毕竟是本地决定的,你本地有的,传送过来,向前兼容是不会有问题的。但如果是接口返回,就比拟恶心了,因为解析回来的这个枚举值,可能本地还没有,这时就会抛出序列化异样。
比方:你的本地枚举类,有一个天气 Enum:SUNNY, RAINY, CLOUDY,如果依据天气计算情绪的办法:guess(WeatcherEnum xx),传入这三个值都是能够的。返回值:Weather guess(参数),那么对方运算后,返回一个 SNOWY,本地枚举里没有这个值,傻眼了。
文章完结
如果本文对你有所帮忙的话,那就点个赞吧
更多分享尽在微信公众号【codeLiveHouse】
公众号回复 “材料” 能够获取大厂面试题/技术文档/电子书等等
往期举荐
面试官居然和我死磕 Maven
生产上数据库死锁,是该程序员祭天了