2016-01-05 7 views
13

Я хотел бы использовать инструкцию java switch, в которой используются имена class как константы case. Возможно ли это как-то? Или мне нужно дублировать имена классов?Возможно ли использовать имя класса в java switch/case statement?

Следующий код не работает из-за ошибки компилятора:

случае выражения должны быть константными выражениями

String tableName = "MyClass1"; 

... 

switch (tableName) { 
case MyClass1.class.getSimpleName(): 
    return 1; 
case MyClass2.class.getSimpleName(): 
    return 2; 
default: 
    return Integer.MAX_VALUE; 
} 

Здесь онлайновая демонстрация выпуска (openjdk 1.8.0_45): http://goo.gl/KvsR6u

+2

Можете ли вы попробовать назначить строки конечным локальным переменным String? –

+1

Какая версия java? Вы получите разные результаты на Java 7/8. – Marged

+0

@Marged Я использую Java 8, но интересуюсь решением для любой версии ... – dedek

ответ

6

Ошибка компилятора уже говорит об этом. Метки case должны быть постоянными выражениями, и ни слова, ни литералы класса, ни результат вызова на них не являются постоянными выражениями.

Рабочий раствор будет:

String tableName = "MyClass1"; 
... 
switch (tableName) { 
    case "MyClass1": 
     return 1; 
    case "MyClass2": 
     return 2; 
    default: 
     return Integer.MAX_VALUE; 
} 

Выражение MyClass1.class.getSimpleName() не проще, чем "MyClass1", но, конечно, не будет никакой проверки во время компиляции, совпадают ли имена существующих классов и инструменты рефакторинга или обфускаторы не замечают отношения между классом MyClass1 и строковым литералом "MyClass1".

Нет решения. Единственное, что вы можете сделать, чтобы уменьшить проблему, - объявить ключи внутри связанного класса для документирования отношений, например.

class MyClass1 { 
    static final String IDENTIFIER = "MyClass1"; 
    ... 
} 
class MyClass2 { 
    static final String IDENTIFIER = "MyClass2"; 
    ... 
} 
... 
String tableName = MyClass1.IDENTIFIER; 
... 
switch (tableName) { 
    case MyClass1.IDENTIFIER: 
     return 1; 
    case MyClass2.IDENTIFIER: 
     return 2; 
    default: 
     return Integer.MAX_VALUE; 
} 

Это документирует отношение к читателю, но инструменты все еще не гарантируют, что фактическое содержимое строки соответствует имени класса. Однако в зависимости от того, чего вы хотите достичь, теперь может быть неактуальным, соответствует ли содержимое строки имени класса ...

+0

Это правильный ответ для меня: * Ярлыки case должны быть постоянными выражениями, и ни литераторы классов, ни результат вызова 'getSimpleName()' на них не являются постоянными выражениями. * – dedek

+0

Хорошее объяснение ** констант постоянной времени компиляции ** можно найти здесь: http://stackoverflow.com/a/3827424/1857897 – dedek

+0

Я думал, что * литералы класса * являются постоянными выражениями, но тогда '' "+ MyClass1.class' должен работать, но он не ... – dedek

8

Вместо использования переключателя, почему бы и нет хранить сопоставления на карте?

Создайте карту String для Integer и сопоставьте все имена классов с их возвращаемым значением.

По запросу, если запись не существует, верните значение по умолчанию. В противном случае верните значение на карте.

+0

Я думал об этом решении, но не был бы 'switch' более эффективным? – dedek

+2

Возможно, но ваш код также будет менее читаемым, так как вам потребуется строка для каждого имени класса, а затем еще несколько для каждого случая. Несколько наносекунд оптимизации, которые вы получите, вероятно, никогда не будут стоить чистки кода, который вы можете использовать с помощью «Карты» –

+1

О, я забыл добавить.Если я правильно помню, 'switch'es on Strings просто [переключится на свой хэш-код] (http://www.benf.org/other/cfr/java7switchonstring.html), если только что-то не изменилось недавно –

2

Вместо Switch..case, почему бы вам не использовать If..Else. Должен работать во всех версиях Java до тех пор, пока я не узнаю.

if (tableName.equals(MyClass1.class.getSimpleName())) { 
    return 1; 
} else if (tableName.equals(MyClass2.class.getSimpleName())) { 
    return 2; 
} else { 
    return Integer.MAX_VALUE; 
} 
+1

Мне действительно не нравятся утверждения 'else if', см. решение' Map' by @ Sam-Sun – dedek

+0

- это зависит от выбора, но до тех пор, пока я не знаю это поддерживается во всех версиях, и вам не потребуется обрабатывать любые зависимости от версии. –

+1

проблема этого решения заключается в том, что в худшем случае ему приходится преодолевать каждую возможность, поэтому люди хотят «переключаться». – Leonmax