2016-01-05 33 views
13

Chciałbym użyć instrukcji java switch, która używa nazw class jako stałych case. Czy to możliwe? Czy muszę powtórzyć nazwy klas?Czy jest możliwe użycie nazwy klasy w instrukcji switch/case języka Java?

następujący kod nie działa z powodu błędu kompilatora:

przypadku wyrażenia musi być stała wyrażenia

String tableName = "MyClass1"; 

... 

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

Tutaj jest demonstracja online emisji (openjdk 1.8.0_45): http://goo.gl/KvsR6u

+2

Czy możesz spróbować przypisać ciągi do końcowych zmiennych lokalnych String? –

+1

Którą wersję Java? Otrzymasz różne wyniki na Java 7/8. – Marged

+0

@ Maraton Używam Java 8, ale interesuje mnie rozwiązanie dla każdej wersji ... – dedek

Odpowiedz

6

Błąd kompilatora już to mówi. Etykiety case muszą być wyrażeniami stałymi, a ich znaki literowe ani wynik wywołania na nich nie są wyrażeniami stałymi.

roztworu roboczego byłoby:

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

Wyrażenie MyClass1.class.getSimpleName() nie jest prostsze niż "MyClass1", ale, oczywiście, nie będzie żadnych check kompilacji czy nazwy odpowiadają istniejących klas i narzędzi Refaktoryzacja lub obfuscators nie zauważają związku między klasą MyClass1 a literałem tekstowym "MyClass1".

Nie ma na to rozwiązania. Jedyną rzeczą, którą możesz zrobić, aby zmniejszyć problem, jest zadeklarowanie kluczy w powiązanej klasie w celu udokumentowania relacji, np.

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

Dokumentuje związek z czytnikiem, ale narzędzia wciąż nie zapewniają, że rzeczywista zawartość ciągów pasuje do nazwy klasy. Jednak w zależności od tego, co chcesz osiągnąć, teraz może stać się nieistotne, czy zawartość ciągu pasuje do nazwy klasy ...

+0

To jest poprawna odpowiedź dla mnie: * Etykiety na kopercie muszą być wyrażeniami stałymi i żadne z nich, ani literówki klasy, ani wynik wywoływania na nich 'getSimpleName()' są wyrażeniami stałymi. * – dedek

+0

Dobre wyjaśnienie ** stałych wyrażeń czasu kompilacji ** można znaleźć tutaj: http://stackoverflow.com/a/3827424/1857897 – dedek

+0

Myślałem, że * klasy literały * są wyrażeniami stałymi, ale wtedy '" "+ MyClass1.class" powinno działać, ale nie działa ... – dedek

8

Zamiast używać przełącznika, dlaczego nie zapisać mapowania na mapie?

Utwórz mapę ciągu do liczby całkowitej i odwzoruj wszystkie nazwy klas na ich wartości zwracane.

Na żądanie, jeśli pozycja nie istnieje, należy zwrócić wartość domyślną. W przeciwnym razie zwróć wartość na mapie.

+0

Myślałem o tym rozwiązaniu, ale czy nie byłoby "przełącznikiem" bardziej wydajnym? – dedek

+2

Być może, ale twój kod będzie również mniej czytelny, ponieważ potrzebujesz linii dla każdej nazwy klasy, a następnie kilku więcej dla każdego przypadku. Nieliczne nanosekundy optymalizacji, które otrzymasz, prawdopodobnie nigdy nie będą warte czystej czystości kodu, który możesz mieć za pomocą 'Map' –

+1

O, zapomniałem dodać.Jeśli dobrze pamiętam, "przełącz" na Strings właśnie [włącz ich hashcode] (http://www.benf.org/other/cfr/java7switchonstring.html), chyba że coś się ostatnio zmieniło –

2

Zamiast Switch..case dlaczego nie używasz If..Else. Powinien działać we wszystkich wersjach java, dopóki nie wiem.

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

Naprawdę nie lubię instrukcji "else if", zobacz rozwiązanie oparte na "Mapie" autorstwa @ Sam-Sun – dedek

+0

, które jest do wyboru, ale dopóki nie dowiem się, jest to obsługiwane we wszystkich wersjach i nie wymaga obsługi żadnych zależności od wersji. –

+1

Problemem tego rozwiązania jest to, że w najgorszym przypadku musi on przejść każdą możliwą możliwość, dlatego ludzie chcą "przełączać". – Leonmax