
软件SDK版本与服务器端API版本不一致的情况十分常见。优秀的SDK能够优雅地处理这种版本差异,兼容潜在的API变更。
对于在Android应用中使用的Java SDK而言,版本兼容性尤为重要,因为用户更新应用的速度往往较慢。应用不应该因为使用了旧版本的SDK而崩溃。
Java枚举的动态兼容性并非理想。以下是一个宠物店API的示例:
假设我们设计了一个代表订单状态的Java枚举:
立即学习“Java免费学习笔记(深入)”;
<code class="java">enum PetOrderStatus {
PLACED,
APPROVED,
DELIVERED,
}</code>用户发现枚举比字符串更方便,因为它能明确指示所有可能的状态,并可以使用switch表达式处理:
<code class="java">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!";
};</code>但是,如何将API响应中的字符串转换为枚举常量呢?最常见的方法是使用valueOf()方法:
<code class="java">PetOrderStatus petOrderStatus = PetOrderStatus.valueOf(statusString.toUpperCase());</code>
这种方法存在潜在问题:API变更。
假设产品经理要求添加“运输中”状态。我们更新SDK:
<code class="java">enum PetOrderStatus {
PLACED,
APPROVED,
IN_TRANSIT,
DELIVERED,
}</code><code class="java">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!";
};</code>部署后,我们收到崩溃报告:
<code>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)</code>这是因为旧版SDK无法识别IN_TRANSIT。valueOf()方法在遇到未知值时会抛出异常。
解决方案
如何避免这种情况呢?一个方案是使用Optional<petorderstatus></petorderstatus>,当值未知时返回Optional.empty()。但这并不理想,因为我们无法区分“没有状态”和“未知状态”。
更强大的方案是存储原始API值,并同时访问原始值和枚举表示:
<code class="java">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,
}
}</code>用户可以这样使用:
<code class="java">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();
};</code>这种设计的好处:
API变更:第二部分
使用新的SDK设计,应用在API变更后不会崩溃。旧版应用会显示“Your order status is: IN_TRANSIT”。如果我们更新SDK和应用,添加IN_TRANSIT到枚举中,用户下次更新后就能看到正确的文本。
以上就是使Java枚举兼容的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号