
软件SDK版本与服务器端API版本不一致的情况十分常见。优秀的SDK能够优雅地处理这种版本差异,兼容潜在的API变更。
对于在Android应用中使用的Java SDK而言,版本兼容性尤为重要,因为用户更新应用的速度往往较慢。应用不应该因为使用了旧版本的SDK而崩溃。
Java枚举的动态兼容性并非理想。以下是一个宠物店API的示例:
假设我们设计了一个代表订单状态的Java枚举:
立即学习“Java免费学习笔记(深入)”;
enum PetOrderStatus { PLACED, APPROVED, DELIVERED,}
用户发现枚举比字符串更方便,因为它能明确指示所有可能的状态,并可以使用switch表达式处理:
String displayText = switch (petOrderStatus) { case PLACED -> "Your order was placed and is being reviewed."; case APPROVED -> "Your order was approved."; case DELIVERED -> "Your order was delivered!";};
但是,如何将API响应中的字符串转换为枚举常量呢?最常见的方法是使用valueOf()方法:
PetOrderStatus petOrderStatus = PetOrderStatus.valueOf(statusString.toUpperCase());
这种方法存在潜在问题:API变更。
假设产品经理要求添加“运输中”状态。我们更新SDK:
enum PetOrderStatus { PLACED, APPROVED, IN_TRANSIT, DELIVERED,}
String displayText = switch (petOrderStatus) { case PLACED -> "Your order was placed and is being reviewed."; case APPROVED -> "Your order was approved."; case IN_TRANSIT -> "Your order is on the way!"; case DELIVERED -> "Your order was delivered!";};
部署后,我们收到崩溃报告:
jQuery的兼容电脑手机端弹出层插件
jQuery的兼容电脑手机端弹出层插件
31 查看详情
Exception in thread "main" java.lang.IllegalArgumentException: No enum constant PetOrderStatus.IN_TRANSIT at java.lang.Enum.valueOf(Enum.java) at PetOrderStatus.valueOf(PetOrderStatus.java)
这是因为旧版SDK无法识别IN_TRANSIT。valueOf()方法在遇到未知值时会抛出异常。
解决方案
如何避免这种情况呢?一个方案是使用Optional,当值未知时返回Optional.empty()。但这并不理想,因为我们无法区分“没有状态”和“未知状态”。
更强大的方案是存储原始API值,并同时访问原始值和枚举表示:
public final class PetOrderStatus { private final String value; private PetOrderStatus(String value) { this.value = value; } public static PetOrderStatus of(String value) { return new PetOrderStatus(value); } public String _value() { return value; } public Value value() { return switch (value) { case "PLACED" -> Value.PLACED; case "APPROVED" -> Value.APPROVED; case "DELIVERED" -> Value.DELIVERED; default -> Value._UNKNOWN; }; } public enum Value { PLACED, APPROVED, DELIVERED, _UNKNOWN, }}
用户可以这样使用:
String displayText = switch (petOrderStatus.value()) { case PLACED -> "Your order was placed and is being reviewed."; case APPROVED -> "Your order was approved."; case DELIVERED -> "Your order was delivered!"; case _UNKNOWN -> "Your order status is: " + petOrderStatus._value();};
这种设计的好处:
保留了枚举的优点,包括详尽性检查。能够处理未知状态,并使用原始API值。
API变更:第二部分
使用新的SDK设计,应用在API变更后不会崩溃。旧版应用会显示“Your order status is: IN_TRANSIT”。如果我们更新SDK和应用,添加IN_TRANSIT到枚举中,用户下次更新后就能看到正确的文本。
以上就是使Java枚举兼容的详细内容,更多请关注创想鸟其它相关文章!
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 chuangxiangniao@163.com 举报,一经查实,本站将立刻删除。
发布者:程序猿,转转请注明出处:https://www.chuangxiangniao.com/p/361874.html
微信扫一扫
支付宝扫一扫