1

我有一个有趣的要求,我们有大量的枚举形式

public enum BpcCmsError {

    ERROR_TYPE_1("Error message 1"), 
    ERROR_TYPE_2("Error message 2"),
    ERROR_TYPE_3("Error message 3");


    private int errorCode;
    private final String errorMessage;
    public static final int ERRORCODE_BASE = 100;

我需要分配一些唯一的错误代码,从一个数字开始并向上计数,所以我有一个构造函数:

private BpcCmsError(String message) {
        this.errorMessage = message;
 }

和一个静态块

static {
        int code = ERRORCODE_BASE;
        for (BpcCmsError error : EnumSet.allOf(BpcCmsError.class)) {
            error.errorCode = ++code;
       }
}

效果很好。

但是,我需要一些额外的灵活性来分配这些错误代码,理想情况下是这样的:

    ERROR_TYPE_1("Error message 1"), 
    ERROR_TYPE_2("Error message 2"),
    ERROR_TYPE_3(200,"Error message for code");

意图是 2-args 构造函数会导致后续错误代码从第一个参数的值开始。在我的情况下,错误代码将是 100、101、200、201 等。当然我需要检查是否应该允许这种跳转,例如,我们可能已经数过了 200。关于如何在 Java 中使用枚举来实现这一点的任何提示?

4

3 回答 3

4

感觉不像您需要枚举...您似乎正在尝试将一系列整数错误代码映射到错误消息

在这种情况下,您需要某种Map

所以你会有一些类似的东西(没有IDE,所以为愚蠢的语法错误道歉)

public class BpcCmsError {
    private Map<int, String> errorMap = new HashMap<int, String>();
    private int lastErrorCode = 0;

    public void addError(String message) {
       errorMap.put(lastErrorCode++, message);
    }

     public void addError(int code, String message) {
       errorMap.put(code, message);
       lastErrorCode = code++;
    }

    public String getMessage(int code) {
       return errorMap.get(code);
    }

}
于 2013-06-08T12:09:27.127 回答
2

显而易见的答案是private static int nextErrorCode每次使用时都有一个并递增它......但这不起作用,因为你不能从枚举构造函数中引用静态字段(这被称为枚举的静态初始化的一部分) . 从Java 7 规范

static从构造函数、实例初始化程序块或该类型的实例变量初始化程序表达式引用不是常量变量(第 4.12.4 节)的枚举类型字段是编译时错误。

解决方法是将计数器保留在一个简单的静态内部类中:

public enum BpcCmsError {

  ERROR_TYPE_1("Error message 1"),
  ERROR_TYPE_2("Error message 2"),
  ERROR_TYPE_3(200, "Error message 3");

  private final int errorCode;
  private final String errorMessage;

  private BpcCmsError(String message) {
    this.errorMessage = message;
    this.errorCode = NextErrorCode.get();
  }

  private BpcCmsError(int errorCode, String message) {
    this.errorMessage = message;
    this.errorCode = NextErrorCode.get(errorCode);
  }

  private static class NextErrorCode {
    private static int nextErrorCode = 100;

    public static int get() {
      return nextErrorCode++;
    }

    public static int get(int errorCode) {
      if (errorCode < nextErrorCode) {
        throw new IllegalArgumentException("Requested error code " + errorCode + " exceeds next valid error code " + nextErrorCode);
      }
      nextErrorCode = errorCode;
      return nextErrorCode++;
    }
  }
}
于 2013-06-08T12:16:10.857 回答
1

我建议你在你的块中保留一个EnumMap错误代码。enumstatic

public enum ErrorCode {

    ERROR_TYPE_1("Error message 1"),
    ERROR_TYPE_2("Error message 2"),
    ERROR_TYPE_3(200, "Error message 3"),
    ERROR_TYPE_4("Error message 1"),
    ERROR_TYPE_5(300, "Error message 2"),
    ERROR_TYPE_6("Error message 3");
    private final int errorCode;
    private final String errorMessage;
    private static final Map<ErrorCode, Integer> ERROR_CODES;
    private static final int ERROR_CODE_BASE = 100;

    static {
        ERROR_CODES = new EnumMap<>(ErrorCode.class);
        int code = ERROR_CODE_BASE;
        for (final ErrorCode ec : values()) {
            if (ec.errorCode > 0) {
                if (ec.errorCode <= code) {
                    throw new ExceptionInInitializerError("Non unique code for " + ec);
                }
                code = ec.errorCode;
            }
            ERROR_CODES.put(ec, code++);            
        }
    }

    private ErrorCode(final String errorMessage) {
        this(-1, errorMessage);
    }

    private ErrorCode(final int errorCode, final String errorMessage) {
        this.errorCode = errorCode;
        this.errorMessage = errorMessage;
    }

    public String getErrorMessage() {
        return errorMessage;
    }

    public int getErrorCode() {
        return ERROR_CODES.get(this);
    }
}

这是非常灵活的——您可以非常轻松地更改代码生成的逻辑。

javaEnumMap也很漂亮,它是Map针对enum键进行优化的。

快速测试:

public static void main(String[] args) throws Exception {
    for(final ErrorCode errorCode : ErrorCode.values()) {
        System.out.println(errorCode + ", code is " + errorCode.getErrorCode());
    }
}

输出:

ERROR_TYPE_1, code is 100
ERROR_TYPE_2, code is 101
ERROR_TYPE_3, code is 200
ERROR_TYPE_4, code is 201
ERROR_TYPE_5, code is 300
ERROR_TYPE_6, code is 301
于 2013-06-08T12:53:07.507 回答