Las declaraciones de cambio con Stringcasos se han implementado en Java SE 7 , al menos 16 años después de que se solicitaron por primera vez. No se proporcionó una razón clara para la demora, pero probablemente tuvo que ver con el rendimiento.
Implementación en JDK 7
La característica ahora se ha implementado javac con un proceso de "des-azúcar"; una sintaxis limpia y de alto nivel que usa Stringconstantes en las casedeclaraciones se expande en tiempo de compilación en un código más complejo siguiendo un patrón. El código resultante utiliza instrucciones JVM que siempre han existido.
A switchcon Stringcasos se traduce en dos interruptores durante la compilación. El primero asigna cada cadena a un número entero único: su posición en el interruptor original. Esto se hace activando primero el código hash de la etiqueta. El caso correspondiente es una ifdeclaración que prueba la igualdad de cadena; Si hay colisiones en el hash, la prueba es en cascada if-else-if. El segundo conmutador refleja eso en el código fuente original, pero sustituye las etiquetas de los casos con sus posiciones correspondientes. Este proceso de dos pasos facilita la preservación del control de flujo del interruptor original.
Interruptores en la JVM
Para obtener más detalles técnicos sobre switch, puede consultar la Especificación JVM, donde se describe la compilación de las instrucciones del conmutador . En pocas palabras, hay dos instrucciones JVM diferentes que se pueden usar para un conmutador, dependiendo de la escasez de las constantes utilizadas por los casos. Ambos dependen del uso de constantes enteras para que cada caso se ejecute de manera eficiente.
Si las constantes son densas, se usan como un índice (después de restar el valor más bajo) en una tabla de punteros de instrucción: la tableswitchinstrucción.
Si las constantes son escasas, se realiza una búsqueda binaria del caso correcto: la lookupswitchinstrucción.
Al quitar el azúcar switcha los Stringobjetos, es probable que se utilicen ambas instrucciones. El lookupswitches adecuado para el primer interruptor de códigos hash para encontrar la posición original de la caja. El ordinal resultante es un ajuste natural para a tableswitch.
Ambas instrucciones requieren que las constantes enteras asignadas a cada caso se ordenen en tiempo de compilación. En tiempo de ejecución, aunque el O(1)rendimiento de tableswitchgeneralmente parece mejor que el O(log(n))rendimiento de lookupswitch, requiere un análisis para determinar si la tabla es lo suficientemente densa como para justificar la compensación espacio-tiempo. Bill Venners escribió un gran artículo que cubre esto con más detalle, junto con una mirada oculta a otras instrucciones de control de flujo de Java.
Antes de JDK 7
Antes de JDK 7, enumpodría aproximarse a un Stringinterruptor basado en. Esto utiliza elvalueOf método estático generado por el compilador en cada enumtipo. Por ejemplo:
Pill p = Pill.valueOf(str);
switch(p) {
case RED: pop(); break;
case BLUE: push(); break;
}