2014-02-10 2 views
1

Я чувствую, что я просто что-то пропустил или, возможно, это не использование перечисления. Довольно много я знаю, что я мог бы очистить этот код с помощью перечисления:java simple switch with enum

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); 

Кроме того, это также можно объявить это перечисление, используя окончательную (который в настоящее время жалуется, когда я пытаюсь), или это уже окончательное?

Спасибо!

+0

Есть причина, почему вы кладете перечисление внутри 'MYConstants', вместо автономных ? –

+0

Я думаю, что «класс» будет работать лучше в этой ситуации. – mrres1

+0

@OP у вас есть несколько ответов здесь; пожалуйста, примите один из них, если он ответит на ваш вопрос. –

ответ

0

Ваш коммутатор выглядит достаточно чистым для меня. Если вы хотите обобщить, я бы не переместил жестко закодированную бизнес-логику в другой блок жестко запрограммированной бизнес-логики. Нажмите его в файл конфигурации или базу данных. Более чистый подход - это таблица поиска (из рода).

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()); 
    } 

} 
+0

Вам не нужно добавлять целочисленное поле в enum для этого? –

+1

Ах, битва между шаблоном нулевого объекта и исключениями бросания начинается ... –

+0

@DavidWallace OK, справа. Ответ обновлен. –

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 и создавая экземпляры новых class с указанными именами. Фактическая декларация enum - это не действительно a class декларация, поэтому не может быть final. Более того, если ваши enum сами константы переопределить или реализовать методы (например, в this example), то каждая enum константа будет анонимный класс расширения Booktype - если enum были final и была перенесена на BookType класса, то такое поведение не будет разрешено; и это не было бы совершенно очевидно, почему.

1

Это действительно зависит от значимости отношений между id и именем. Я попытался бы удалить 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; 
    } 
} 
0

Да, вы что-то упустили и вот оно.Это все вам нужно.

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

Вы делаете не необходимо преобразовать результат и/или от int.

Вы делаете не необходимости преобразовать его назад и вперед в/из bookTypeId, используйте valueOf.

Если вам нужно сделать тип книги более чем просто enum, то добавьте в него атрибуты.

Что вам не хватает, что само перечисление может быть использован в других местах в вас программа, она может быть сохранена в базе данных по названию и восстановить с помощью метода valueOf.

Позвольте вашему enum быть простым!

Вместо коммутатора - который, кажется, получает String форму enum просто сделать:

String name = genre.name(); 
+0

Если я не ошибаюсь, значения enum действительно должны быть написаны во всех шапках. В противном случае хороший пост. –

+0

@ABoschman - Это похмелье от старых дней C, когда было трудно сказать важное значение того, что было постоянным, а что нет. Java не C. – OldCurmudgeon

+0

Ой, я тоже делал это неправильно? У моих профессоров есть кое-какие объяснения. –