2012-04-30 1 views
8

Почему невозможно использовать значения перечислений в виде строк в корпусе коммутатора? (Или, что случилось с этим :)Использование строковых представлений значений перечисления в ящике коммутатора

String argument; 
switch (argument) { 
    case MyEnum.VALUE1.toString(): // Isn't this equal to "VALUE1" ? 
    // something  
break; 
    case MyEnum.VALUE2.toString(): 
    // something else 
break; 

ответ

22

Вы можете использовать только строки, которые известны во время компиляции. Компилятор не может определить результат этого выражения.

Может быть, вы можете попробовать

String argument = ... 
switch(MyEnum.valueOf(argument)) { 
    case VALUE1: 

    case VALUE2: 
+0

Важно то, что 'VALUE1' является статическим. У вас может быть свой собственный 'myValueOf()', и он все равно будет работать. –

+0

Черт, 'valueOf()' вообще не находится в 'case'. Я удаляю этот предыдущий комментарий, не могу смотреть на него. Еще раз спасибо. – Bloke

+3

Будьте осторожны с valueOf(), которые бросают NPE и IllegalArgumentException, если аргумент недействителен. Код Блока имеет смысл избегать обращения с этим исключением (но, к сожалению, не работает). – Nereis

5

случае MyEnum.VALUE1.toString(): // Не это равно "VALUE1"?

Нет, не обязательно: вы можете предоставить свою собственную реализацию toString()

public enum MyType { 
VALUE1 { 
    public String toString() { 
     return "this is my value one"; 
    } 
}, 

VALUE2 { 
    public String toString() { 
     return "this is my value two"; 
    } 
} 

}

Кроме того, кто-то, кто поддерживает ваш код может добавить эту реализацию после выхода компании , Вот почему вы не должны полагаться на значения String и придерживаться использования числовых значений (в соответствии с константами MyEnum.VALUE1, MyEnum.VALUE2 и т. Д.) Вашего enum.

+0

"числовые значения ваших перечислений"? Вы имеете в виду перечисление константных имен ваших перечислений? – assylias

+0

@assylias Конечно, я определенно подразумеваю использование постоянных имен, а не целых литералов, соответствующих этим именам! Спасибо, я отредактировал ответ, чтобы отразить этот важный момент. – dasblinkenlight

+0

О, право. Это хорошее объяснение, спасибо. – Bloke

1

Чтобы добавить комментарии Питера Lawrey, в взглянуть на this пост с прошлого года, который обсуждает Переключение на строки в Java до и после JDK7.

+0

Даже не знал, что это было невозможно до JDK7. Спасибо, нашел отличную ссылку об этом в комментарии там: [link] (http://www.xefer.com/2006/12/switchonstring) - это лучший способ обработки ввода String? – Bloke

+1

Ну, пурист может сказать, что вы вообще не должны использовать оператор switch/case на языке OOP; вместо этого вы должны пойти с полиморфизмом стратегии для решения чего-то вроде этого.IMO, если это понятно, кратким, ремонтопригодным и эффективным, case/switch - лучшее решение во многих сценариях. – Sanjeev

-1

EDIT: Извинения за ответ C# на вопрос Java. Я не знаю, что пошло не так.

В нем есть возможно использование строковых значений (включая строковые значения перечислений). Тем не менее, вы можете использовать только константы времени компиляции. Вы вызываете метод, ToString(), который необходимо оценить во время выполнения.

По состоянию на C# 6, вы можете использовать эту постоянную альтернативу: case nameof(SomeEnum.SomeValue):

Nameof() вычисляется во время компиляции, просто в строку, которая соответствует (неквалифицированное) имя данной переменной, тип или член , Его значение соответствует значению SomeEnum.ToString().