登录
首页 >  文章 >  java教程

使Java枚举兼容

时间:2025-02-12 16:28:03 221浏览 收藏

在IT行业这个发展更新速度很快的行业,只有不停止的学习,才不会被行业所淘汰。如果你是文章学习者,那么本文《使Java枚举兼容》就很适合你!本篇内容主要包括##content_title##,希望对大家的知识积累有所帮助,助力实战开发!

使Java枚举兼容

软件SDK版本与服务器端API版本不一致的情况十分常见。优秀的SDK能够优雅地处理这种版本差异,兼容潜在的API变更。

对于在Android应用中使用的Java SDK而言,版本兼容性尤为重要,因为用户更新应用的速度往往较慢。应用不应该因为使用了旧版本的SDK而崩溃。

Java枚举的动态兼容性并非理想。以下是一个宠物店API的示例:

假设我们设计了一个代表订单状态的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!";
};

部署后,我们收到崩溃报告:

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_TRANSITvalueOf()方法在遇到未知值时会抛出异常。

解决方案

如何避免这种情况呢?一个方案是使用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到枚举中,用户下次更新后就能看到正确的文本。

今天带大家了解了的相关知识,希望对你有所帮助;关于文章的技术知识我们会一点点深入介绍,欢迎大家关注golang学习网公众号,一起学习编程~

相关阅读
更多>
最新阅读
更多>
课程推荐
更多>