2016-03-18 2 views
1

У меня есть следующий перечислителя:Как получить значение из перечисления без переменных

public enum UserChoice { 
    QUIT, LIST_BOOKS, CHECKOUT_BOOK, RETURN_BOOK, LIST_MOVIES, 
    CHECKOUT_MOVIE, RETURN_MOVIE, USER_INFORMATION 
} 

, и я хотел бы использовать его в распределительном заявлении, который принимает Int в качестве параметра. Тем не менее, мне нужно, чтобы получить ИНТ значение перечисления, так что я делаю это:

try { 
    int option = Reader.getUserOption(); 
} catch (InputMismatchException ex) { 
    option = 8; 
} 

switch (option) { 
    case UserChoice.QUIT.ordinal(): 
     break; 
    case UserChoice.LIST_BOOKS.ordinal(): 
     Printer.printBooks(library); 
     break; 
    case UserChoice.CHECKOUT_BOOK.ordinal(): 
     // code 
     break; 
    case UserChoice.RETURN_BOOK.ordinal(): 
     // code 
     break; 
    case UserChoice.LIST_MOVIES.ordinal(): 
     Printer.printMovies(library); 
     break; 
    case UserChoice.CHECKOUT_MOVIE.ordinal(): 
     // code 
     break; 
    case UserChoice.RETURN_MOVIE.ordinal(): 
     // code 
     break; 
    case UserChoice.USER_INFORMATION.ordinal(): 
     System.out.println(currentUser); 
     break; 
    default: 
     Printer.printInvalidOptionMessage(); 
     break; 
    } 

Есть ли способ бросить Int в значение перечисления или кто я могу добиться этого с помощью перечислений. В конце концов, я хочу указать имя нумератора для каждого случая, чтобы я мог четко понимать, что делает каждый случай, потому что ранее я использовал значения int для этого.

+0

В конце концов, то, что я сделал после @Darth Android, @ Xoce и @Jim Garrison ответы меняется от 'int' до' UserChoice', поэтому 'UserChoice option = UserChoice.values ​​() [Reader.getUserOption() ]; 'и установите опцию' INVALID_OPTION' (новое значение, добавленное в перечисление) в блоке catch. – lmiguelvargasf

ответ

3

Создайте дополнительное значение перечисления для INVALID_CHOICE и используйте его. Но более того, вы полностью отключаете пользовательский ввод от заказа (и значение ordinal) перечисления.

Вот пример того, как это сделать.

public static enum UserChoice { 
    /* 
    * Establish the mapping between the enum value (the semantic action) 
    * and the user's input. This can be adapted to whatever form the user 
    * input takes and is decoupled from the ordinal values. It's all in 
    * one place here and a change here does not need a change anywhere else. 
    */ 
    QUIT   (0), 
    LIST_BOOKS  (1), 
    CHECKOUT_BOOK (2), 
    RETURN_BOOK  (3), 
    LIST_MOVIES  (4), 
    CHECKOUT_MOVIE (5), 
    RETURN_MOVIE (6), 
    USER_INFORMATION(7), 
    INVALID_CHOICE (Integer.MIN_VALUE); 

    /* 
    * The mapping, and its initialization, using the new features in Java 8 
    */ 
    private static final Map<Integer,UserChoice> valueMap = Arrays.stream(UserChoice.values()).collect(Collectors.toMap(UserChoice::getValue, Function.identity())); 

    /* 
    * A method to convert from user input (int in this case) to the corresponding 
    * enum value based on the mapping above. 
    */ 
    public static UserChoice fromUserInput(int input) { 
     return Optional.ofNullable(valueMap.get(input)).orElse(INVALID_CHOICE); 
    } 

    /* 
    * Per-enum value and method 
    */ 
    private final int userValue; 
    private UserChoice(int userValue) { this.userValue = userValue; } 
    public int getValue() { return this.userValue; } 
} 

/* 
* Simple test 
*/ 
public static void main(String args[]) throws Exception 
{ 
    for (int i=0; i<10; i++) 
    { 
     UserChoice c = UserChoice.fromUserInput(i); 
     System.out.printf("Input %d enum is %s\n", i, c.toString()); 
    } 
} 
+0

option is int, который пользователь вводит через консоль – lmiguelvargasf

+1

Я переписал свой пример, чтобы показать, как это сделать таким образом, чтобы полностью отделить пользовательский ввод от порядковая позиция. Хотя вы можете использовать порядковый номер, мой пример полностью инкапсулирует отображение с пользовательского ввода на значение перечисления и может быть адаптирован независимо от того, как пользователь вводит свой выбор. –

+0

Вы совершенно правы @ Jim Garrison, так что ваш ответ заслуживает подтверждения. – lmiguelvargasf

2

UserChoice.values()[option] должен это сделать. Вы можете отдельно определить, что option >= 0 и option < UserChoice.values().length.

Опасайтесь, что существует множество ресурсов, защищающих использование или хранение ordinal, поскольку все номера будут изменены, если вы добавите, удалите или измените порядок значений перечисления. Если число является неотъемлемой частью вашего перечислимого типа, RETURN_MOVIE всегда должно быть разрешено для опции 6 - вы можете сделать его параметром и свойством конструктора константы перечисления и обеспечить поиск через отдельную карту.

+0

Спасибо вашему решению, дайте мне хит, как его решить :) – lmiguelvargasf

0

Пожалуйста, попробуйте UserChoice.values()[option] где опция начинается с 0 и option<UserChoice.values().length

+0

Дело в том, что я хочу видеть в коде имя значения enum. В противном случае я предпочитаю использовать то, что у меня было ранее (номер, помещенный непосредственно в код) – lmiguelvargasf

1

If Reader.getUserOption() возвращает параметр из UserChoice Enumerator то не литой не нужен ...

Пример:

switch (Reader.getUserOption()) { 
      case CHECKOUT_MOVIE: 

       break; 
      case LIST_BOOKS: 

       break; 
      case QUIT: 

       break; 

      default: 
       break; 
     } 

вас конечно же, нужно будет сделать корпус переключателя внутри попытки.

Edit:

Если метод getUserOption возвращает Int и ИНТ является Порядковым представлением вариантов в счетчику:

QUIT, ........... , USER_INFORMATION

0, ..............., 7

затем сделать это:

switch (UserChoice.values()[Reader.getUserOption()]) { 
+0

Reader.getUserOption() возвращает int, который задан пользователем, так что это моя проблема, как передать этот int в значение перечисления – lmiguelvargasf

+0

Я обновляю свой ответ. посмотрите и дайте мне знать –

+0

Ваше решение действительно, но вы знаете, что я должен использовать QUIT вместо UserChoice.QUIT для компиляции – lmiguelvargasf

0

Вам нужно для поиска перечисления по индексу:

try { 
    int option = Reader.getUserOption(); 
} catch (InputMismatchException ex) { 
    option = 8; 
} 

switch (UserChoice.values()[option]) { 
    case QUIT: 
     break; 
    case LIST_BOOKS: 
     Printer.printBooks(library); 
     break; 
    case CHECKOUT_BOOK: 
     // code 
     break; 
    case RETURN_BOOK: 
     // code 
     break; 
    case LIST_MOVIES: 
     Printer.printMovies(library); 
     break; 
    case CHECKOUT_MOVIE: 
     // code 
     break; 
    case RETURN_MOVIE: 
     // code 
     break; 
    case USER_INFORMATION: 
     System.out.println(currentUser); 
     break; 
    default: 
     Printer.printInvalidOptionMessage(); 
     break; 
    } 

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

+0

Спасибо! Ваш ответ действительно хорош и решает все. – lmiguelvargasf

+1

Это прерывается, если вы изменили порядок или количество параметров. У вас должно быть преобразование ввода в enum в перечисление, чтобы все было в одном месте. Перечисление должно иметь статический метод для поиска ввода и возврата значения перечисления, I.e. 'UserChoice.fromUserInput (ввод строки)' –

Смежные вопросы