Les instructions de commutation avec des String
cas ont été implémentées dans Java SE 7 , au moins 16 ans après leur première demande. Une raison claire de ce retard n'a pas été fournie, mais elle était probablement liée à la performance.
Implémentation dans JDK 7
La fonction a maintenant été mise en œuvre javac
avec un processus de "désucrage"; une syntaxe propre et de haut niveau utilisant des String
constantes dans les case
déclarations est développée au moment de la compilation en un code plus complexe suivant un modèle. Le code résultant utilise des instructions JVM qui ont toujours existé.
Un switch
avec String
cas est traduit en deux commutateurs lors de la compilation. Le premier mappe chaque chaîne à un entier unique — sa position dans le commutateur d'origine. Cela se fait en activant d'abord le code de hachage de l'étiquette. Le cas correspondant est une if
instruction qui teste l'égalité des chaînes; s'il y a des collisions sur le hachage, le test est en cascade if-else-if
. Le deuxième commutateur reflète cela dans le code source d'origine, mais remplace les étiquettes de cas avec leurs positions correspondantes. Ce processus en deux étapes permet de conserver facilement le contrôle de flux du commutateur d'origine.
Commutateurs dans la JVM
Pour plus de détails techniques switch
, vous pouvez vous référer à la spécification JVM, où la compilation des instructions de commutateur est décrite. En résumé, deux instructions JVM différentes peuvent être utilisées pour un commutateur, selon la rareté des constantes utilisées par les cas. Les deux dépendent de l'utilisation de constantes entières pour chaque cas pour s'exécuter efficacement.
Si les constantes sont denses, elles sont utilisées comme index (après soustraction de la valeur la plus basse) dans un tableau de pointeurs d'instructions - l' tableswitch
instruction.
Si les constantes sont rares, une recherche binaire du cas correct est effectuée - l' lookupswitch
instruction.
Lors du dépuchage switch
d' String
objets sur , les deux instructions sont susceptibles d'être utilisées. Le lookupswitch
convient au premier interrupteur sur les codes de hachage pour trouver la position d'origine du boîtier. L'ordinal résultant est un ajustement naturel pour a tableswitch
.
Les deux instructions nécessitent que les constantes entières attribuées à chaque cas soient triées au moment de la compilation. Au moment de l'exécution, bien que les O(1)
performances de tableswitch
généralement semblent meilleures que les O(log(n))
performances de lookupswitch
, elles nécessitent une analyse pour déterminer si la table est suffisamment dense pour justifier le compromis espace-temps. Bill Venners a écrit un excellent article qui couvre cela plus en détail, ainsi qu'un regard sous le capot sur d'autres instructions de contrôle de flux Java.
Avant JDK 7
Avant JDK 7, enum
pouvait s'approcher d'un String
commutateur basé sur. Cela utilise lavalueOf
méthode statique générée par le compilateur sur chaque enum
type. Par exemple:
Pill p = Pill.valueOf(str);
switch(p) {
case RED: pop(); break;
case BLUE: push(); break;
}