web-dev-qa-db-fra.com

Est-il possible d'utiliser un nom de classe dans Java switch / case statement?

Je voudrais utiliser une instruction Java switch, qui utilise class noms comme constantes case. Est-ce possible d'une manière ou d'une autre? devez dupliquer les noms de classe?

Le code suivant ne fonctionne pas en raison de erreur du compilateur :

les expressions de cas doivent être des expressions constantes

String tableName = "MyClass1";

...

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

Voici une démonstration en ligne du problème (openjdk 1.8.0_45): http://goo.gl/KvsR6

19
dedek

L'erreur du compilateur le dit déjà. Les étiquettes de cas doivent être des expressions constantes et ni les littéraux de classe ni le résultat de l'appel de getSimpleName() sur eux ne sont des expressions constantes.

Une solution de travail serait:

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

L'expression MyClass1.class.getSimpleName() n'est pas plus simple que "MyClass1", Mais, bien sûr, il n'y aura pas de vérification au moment de la compilation si les noms correspondent aux classes existantes et les outils de refactorisation ou les obfuscateurs ne remarquent pas la relation entre la classe MyClass1 et le littéral de chaîne "MyClass1".

Il n'y a pas de solution à cela. La seule chose que vous pouvez faire pour réduire le problème est de déclarer les clés dans la classe associée pour documenter une relation, par ex.

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

Cela documente la relation avec le lecteur, mais les outils ne garantiront toujours pas que le contenu réel de la chaîne correspond au nom de la classe. Cependant, en fonction de ce que vous souhaitez réaliser, il peut ne plus être pertinent maintenant, que le contenu de la chaîne corresponde au nom de la classe…

11
Holger

Au lieu d'utiliser un commutateur, pourquoi ne pas stocker les mappages dans une carte?

Créez une mappe de chaîne en nombre entier et mappez tous les noms de classe à leur valeur de retour.

Sur demande, si l'entrée n'existe pas, retournez la valeur par défaut. Sinon, renvoyez la valeur dans la carte.

8
Sam Sun

Au lieu de Switch..case, pourquoi n'utilisez-vous pas If..Else. Devrait fonctionner dans toutes les versions de Java jusqu'à ce que je sache.

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