基于字符串内容的枚举值

Enum valueof based on String contents

我正在尝试使用枚举来包装我的应用程序中的某些错误代码。

public enum ErrorStatus
{
    PAGE_NOT_FOUND("http 404", "lorem ipsum")
    private final String code;
    private final String description;
        private ErrorStatus(String code, String description)
            {
            this.code = code;
            this.description = description;
        }
    public String getDescription()
    {
        return description;
    }
}

当我收到错误时,它是一个带有代码的字符串,例如"http 404"。

"http 404"(或任何其他错误代码)似乎不是清晰易读的枚举名称:

http_404("page not found", "lorem ipsum")

我发现 valueOf()name() 方法不能被覆盖,我想防止其他人错误地在字符串值上使用 valueOf() 而不是自定义实现用不同的名字。

将枚举映射到该字符串值的最简洁方法是什么?

您可以使用映射来保存映射代码枚举。

enum ErrorStatus {    

    PAGE_NOT_FOUND("404", "lorem ipsum");

    private static class Holder {
        private static Map<String, ErrorStatus> MAP = new HashMap<>();
    }

    private String code;
    private String description;

    private ErrorStatus(String code, String description) {
        this.code = code;
        this.description = description;
        Holder.MAP.put(code, this);
    }

    public static ErrorStatus fromCode(String code) {
        ErrorStatus error =  Holder.MAP.get(code);
        if(error == null) {
            throw new IllegalArgumentException();
        }
        return error;
    }
}

然后像这样称呼它:

ErrorStatus status = ErrorStatus.fromCode("404"); //PAGE_NOT_FOUND

诀窍是 class 加载程序在枚举 class 之前初始化静态内部 class 以便您可以在枚举构造函数中使用映射,这意味着代码最少。

为了将枚举映射到它的代码,您只需添加一个方法来给出代码值:

public String code() { return this.code; }

There seems no way to prevent valueof or override it.

不,你不能这样做是对的。但是您可以使用 public 静态最终字段创建 class。

class ErrorStatus {    

    public static final ErrorStatus PAGE_NOT_FOUND = new ErrorStatus("404", "lorem ipsum");
    //override toString, hashCode and equals

    //same code as in the enum

}

编辑: 阅读您的评论后,我认为您正在寻找这样的东西。

import java.util.HashMap;
import java.util.Map.Entry;


public enum ErrorStatus {

    PAGE_NOT_FOUND("404", "Description for error 404");

    private static final HashMap<String, ErrorStatus> ERRORS_BY_CODE;
    private static final HashMap<String, ErrorStatus> ERRORS_BY_DESCR;
    static {
        ERRORS_BY_CODE = new HashMap<String, ErrorStatus>();
        ERRORS_BY_CODE.put("404", PAGE_NOT_FOUND);
        ERRORS_BY_DESCR = new HashMap<String, ErrorStatus>();
        ERRORS_BY_DESCR.put("Description for error 404", PAGE_NOT_FOUND);
    }

所以这里最重要的是 HashMap 的使用,就像走走建议的那样。如果你想有效地通过给定代码查找描述,你需要一个地图,如果你想通过给定的描述有效地查找代码,你需要一个也为此绘制地图。

如果您有 "404""500" 之类的字符串并希望获得相应的描述,您可以使用

public static ErrorStatus getErrorByCode(String code) {
    return ERRORS_BY_CODE.get(code);
}

如果你有像"Description for error 404"这样的描述并且想得到相应的错误代码你可以使用

public static ErrorStatus getErrorByDescr(String descr) {
    return ERRORS_BY_DESCR.get(descr);
}

如果您只有一个字符串 包含 描述,它会变得有点令人讨厌。这不是最有效的方法,但假设您不会有那么多错误代码,那没关系。所以如果我们有一个像 "Here is the description of the page not found error 'Description for error 404'" 这样的字符串,那么你可以使用

public static ErrorStatus getErrorByString(String str) {
    for (Entry<String, ErrorStatus> entry : ERRORS_BY_DESCR.entrySet()){
        if (str.contains(entry.getKey())) {
            return entry.getValue();
        }
    }
    return null;
}

小心最后一个方法,因为它 returns 如果没有找到任何东西,它就会返回 null 并且只给出它成功的第一个错误对象(虽然代码中可以有多个错误描述)。