带枚举的java简单开关

时间:2014-02-10 23:31:52

标签: java enums

我觉得我只是缺少一些东西,或者这可能不是枚举的用法。我知道我可以使用枚举来清理这段代码:

    int bookTypeId = 1; //dynamic
    String bookTypeName;
    switch (bookTypeId) {
    case 1:
        bookTypeName = "Fantasy";
        break;
    case 2:
        bookTypeName = "Horror";
        break;
    case 3:
        bookTypeName = "Action";
        break;
    default:
        bookTypeName = "Error";
    }

所以我做了,我将它存储在另一个类中,它看起来像:

public static enum BookType {
        HORROR("Horror"), FANTASY("Fantasy"), ACTION("Action"), ERROR("Error");

    private String name;

    BookType(String name) {
        this.name = name;
    }

    public String getType() {
        return name;
    }
}

现在使用它:

switch (bookTypeId) {
    case 1:
        bookTypeName = MYConstants.BookType.FANTASY.getType();
        break;
    case 2:
        bookTypeName = MYConstants.BookType.HORROR.getType();
        break;
    case 3: 
        bookTypeName = MYConstants.BookType.ACTION.getType();
        break;
    default:
        bookTypeName = MYConstants.BookType.ERROR.getType();
    }

我想更进一步,并清理我的这个switch语句的主类(这就是为什么我开始查看枚举的原因,因为现在它似乎做了同样的事情。)

是否可以在枚举内移动此开关/外壳?然后以诸如

之类的方式使用枚举
bookTypeName = MYConstants.BookType.getType(bookTypeId);

也可以使用final声明这个枚举(当我尝试时它正在抱怨),还是已经是最终的?

谢谢!

5 个答案:

答案 0 :(得分:2)

如下所示?

public static enum BookType {

    HORROR(1, "Horror"),
    FANTASY(2, "Fantasy"),
    ACTION(3, "Action");

    private static final Map<Integer, BookType> LOOKUP;

    static {
        LOOKUP = new HashMap<>();
        for (final BookType type : values()) {
            LOOKUP.put(type.id, type);
        }
    }

    public static BookType getById(final int id) {
        final BookType bt = LOOKUP.get(id);
        if (bt == null) {
            throw new IllegalArgumentException("Invalid book id " + id);
        }
        return bt;
    }

    private final int id;
    private final String name;

    BookType(final int id, final String name) {
        this.id = id;
        this.name = name;
    }

    public String getType() {
        return name;
    }
}

用法:

final BookType type = BookType.getById(bookTypeId);

您可以删除String媒体资源并覆盖toString()

@Override
public String toString() {
    final String name = name();
    return name.substring(0, 1) + name.substring(1).toLowerCase();
}

要回答您的上一个问题,enum不能是finalenum是句法糖;编译器将通过首先创建class BookType extends Enum<BookType以及具有指定名称的新static final的创建class实例来消除它。实际的enum声明本身并非真的 class声明,因此不能final。此外,如果您的enum常量本身覆盖或实现方法(例如this example中),那么每个enum常量将是一个扩展Booktype的匿名类 - 如果{{1} } enum被转换到final类,然后不允许这种行为;并且为什么不是完全明显的。

答案 1 :(得分:1)

我认为你正在寻找这种模式。

public enum BookType {

    INVALID(0),
    HORROR(1),
    FANTASY(2),
    ACTION(3),
    ERROR(4);

    private int value;

    private BookType(int value) {
        this.value = value;
    }

    public int getValue() {
        return value;
    }

    public String toString(){
        return super.toString().toLowerCase();
    }

    public static BookType getInstance(int value) {
        for (BookType type : BookType.values()) {
            if (value == type.value) {
                return type;
            }
        }
        return INVALID;
    }

    public static void main(String[] args){
        BookType b1 = BookType.HORROR;
        System.out.println(b1.toString());

        BookType b2 = BookType.getInstance(3);
        System.out.println(b2.toString());
    }

}

答案 2 :(得分:1)

这实际上取决于id和name之间关系的重要性。我会尝试一起消除int id。如果无法做到这一点,请考虑将其作为枚举中的字段。

public static enum BookType {
  HORROR(1, "Horror"), FANTASY(2, "Fantasy"), ACTION(3, "Action"), ERROR(-1, "Error");

  private String name;
  private int typeCode;

  BookType(int typeCode, String name) {
    this.typeCode = typeCode;  
    this.name = name;
  }

  public String getName() {
      return name;
  }

  public int getTypeCode(){
    return typeCode;
  }

  public static BookType getFromTypeCode(int typeCode){
    for(BookType bookType : BookType.values()){
      if(bookType.getTypeCode() == typeCode){
        return bookType;
      }
    }
    return BookType.ERROR;
  }
}

答案 3 :(得分:0)

你的开关看起来很干净。如果你想要概括,我不会将硬编码的业务逻辑转移到另一块硬编码的业务逻辑上。将其推送到配置文件或数据库。更干净的方法是查找表(各种)。

答案 4 :(得分:0)

是的,你错过了什么,现在就是这样。这是您需要的全部

enum Genre {
    Unknown,
    Fantasy,
    Horror,
    Action,
    Romance;
}

需要将结果转换为int和/或来自bookTypeId

需要在valueOf之间来回转换,使用enum

如果您需要使图书类型不仅仅是valueOf,那么请为其添加属性。

您缺少的是枚举本身可以在您的程序的其他地方使用,它可以按名称保存到数据库并通过enum方法恢复。

让你的String变得简单!

而不是您的切换 - 似乎只是enum的{​​{1}}形式:

String name = genre.name();