我觉得我只是缺少一些东西,或者这可能不是枚举的用法。我知道我可以使用枚举来清理这段代码:
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声明这个枚举(当我尝试时它正在抱怨),还是已经是最终的?
谢谢!
答案 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
不能是final
。 enum
是句法糖;编译器将通过首先创建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();