Appearance
不建议返回值用枚举
看在前面
第一种回答(来自孤尽)

原文如上。扩展解释:由于升级原因,导致双方的枚举类不尽相同,在接口解析,类反序列化时出现异常。
Java中出现的任何元素,在Gosling的角度都会有背后的思考和逻辑。比如:接口、抽象类、注解、和本文提到的枚举。尽管并非绝对完美,但Java的顶层抽象已经是天才级了。枚举有好处,类型安全,清晰直接,还可以使用等号来判断,也可以用在switch中。它的劣势也是明显的,就是不要扩展。
可是为什么区分了返回值和参数呢,如果不兼容,那么两个都有问题,怎么允许参数可以有枚举。当时的考虑,如果参数也不能用,那么枚举几乎无用武之地了。参数输出,毕竟是本地决定的,你本地有的,传送过去,向前兼容是不会有问题的。但如果是接口返回,就比较恶心了。因为解析回来的这个枚举值,可能本地还没有,这时就会抛出序列化异常。
比如:你的本地枚举类,有一个天气Enum:SUNNY, RAINY, CLOUDY。如果根据天气计算心情的方法:guess(WeatcherEnum xx),传入这三个值都是可以的。返回值:Weather guess(参数),那么对方运算后,返回一个SNOWY,本地枚举里没有这个值,傻眼了。
第二种回答(来自北南)
使用枚举的确会带来扩展兼容性的问题,这点很多答主都说过了。我来说明为什么参数上可以使用枚举。
咱们先假定对枚举的扩展只是新增值,而不是减少值。比如说性别中本来是男和女,现在要增加一个transgender。但我们极少极少会有需求说,把性别中的已有男或者女去掉。(我觉得这个假设是参数可以使用枚举型的前提)
在这个假定下,接口中使用枚举型分为参数和返回值两种情况(如孤尽兄在java开发手册中所述)。
不管是微服务之间的互相调用,还是手机客户端到服务器的调用,都受不停机的约束。在不停机的情况下,服务器端和客户端是很难一起更新的。往往我们是服务器端先来支持新feature,然后再来逐步更新客户端。我想孤尽兄说参数可以使用枚举型,也是基于这种更新升级方式。
因为服务器端如果突然开始返回transgender这个新性别,客户端吃不进去(反序列化不了),客户端就炸了。但如果服务器端只是在参数上开始接受新性别,那就不怕老客户端。反正老客户端还在那里继续发送男和女这两种性别,服务器端都认识,就不会出错。两边可以一直相安无事,慢慢等所有客户端都升级。
但是呢,如果我们用string来代替枚举,服务器端贸然返回一个新的值,客户端不知道怎么处理。这时也可能会产生其他问题,比如说钱算错了之类业务层面的问题。所以客户端代码可能要先更新一点,让其能处理这个新的值。我觉得阿里把这个标准放在手册里,也是多年的经验教训,两害相权取其轻吧。
因为很多应用是没法强制客户端一起更新的。尤其是手机移动客户端,ios可能还要审核,很难做到客户端和服务器端同步更新。如果是微服务,也很难在不停机的情况下,把通过枚举耦合两个微服务一起更新。