970 votos

Instrucción Switch con Cadenas de caracteres en Java

¿Por qué no puedo cambiar en una Cadena en Java?

Es esta funcionalidad va a ser puesto en una posterior versión de Java?

Puede que alguien me apunte a un artículo, o a ellos mismos explican por qué yo no puedo hacer esto, como en el de las técnicas de Java de la instrucción switch funciona?

982voto

erickson Puntos 127945

Interruptor de declaraciones con String de los casos se han implementado en Java SE 7, al menos, 16 años después de que se solicita por primera vez. Una clara razón para el retraso no fue proporcionado, pero es probable que tenían que ver con el rendimiento.

Aplicación en el JDK 7

La característica ya ha sido implementado en javac con un "de-endulzamiento" del proceso; una limpia, de alto nivel de la sintaxis que utiliza String constantes en case de las declaraciones se expande en tiempo de compilación en código más complejo siguiendo un patrón. El código resultante se utiliza instrucciones de la JVM que siempre han existido.

Un switch con String de los casos se traduce en dos interruptores durante la compilación. Los primeros mapas de cada cadena a un entero único-su posición en el original interruptor. Esto es hecho por primera puesta en el código hash de la etiqueta. El correspondiente caso es un if afirmación de que las pruebas de cadena de igualdad; si hay colisiones en el hash, el examen es una cascada if-else-if. El segundo interruptor de los espejos que en el código fuente original, pero sustituye el caso de las etiquetas con sus correspondientes posiciones. Este proceso de dos pasos hace que sea fácil para preservar el control de flujo de la original interruptor.

Los interruptores en la JVM

Para obtener más técnica de la profundidad en switch, puede referirse a que la JVM de Especificación, donde la compilación de sentencias switch se describe. En pocas palabras, existen dos tipos de instrucciones de la JVM que puede ser utilizado para cambiar un poco, dependiendo de la dispersión de las constantes utilizadas por los casos. Ambos dependen del uso de constantes enteras, para cada caso, para ejecutar de manera eficiente.

Si las constantes son densos, que se utiliza como un índice (después de restar el valor más bajo) en una tabla de los punteros de instrucción- tableswitch instrucción.

Si las constantes son escasos, una búsqueda binaria para el caso correcto se realiza- lookupswitch instrucción.

En la de-adición de sacarosa en un switch sobre String objetos, tanto las instrucciones que se vayan a usar. La lookupswitch es adecuado para el primer interruptor de códigos hash para encontrar la posición original de la caja. El resultado ordinal es un ajuste natural para un tableswitch.

Ambas instrucciones requieren las constantes enteras asignado a cada caso de ser clasificados en tiempo de compilación. En tiempo de ejecución, mientras que el O(1) rendimiento de tableswitch aparece, generalmente, mejor que el O(log(n)) rendimiento de lookupswitch, se requiere de un análisis para determinar si la mesa es lo suficientemente densa como para justificar el espacio-tiempo de compensación. Bill Venners escribió un gran artículo que cubre esto con más detalle, junto con un bajo-la-campana buscar en otras Java instrucciones de control de flujo.

Antes de JDK 7

Antes de JDK 7, enum podría aproximar String-base del interruptor. Este utiliza la estática valueOf método generado por el compilador en cada enum tipo. Por ejemplo:

Pill p = Pill.valueOf(str);
switch(p) {
  case RED:  pop();  break;
  case BLUE: push(); break;
}

120voto

JeeBee Puntos 11882

Si usted tiene un lugar en el código donde se puede cambiar en una Cadena, entonces puede ser mejor para refactorizar la Cadena ser una enumeración de los posibles valores que puede cambiar. Por supuesto, usted puede limitar el potencial de los valores de las Cadenas de caracteres que puede tener para aquellos en la enumeración, que puede o no puede ser deseado.

Por supuesto, la enumeración podría tener una entrada para 'otros', y un fromString(Cadena) método, entonces usted podría tener

ValueEnum enumval = ValueEnum.fromString(myString);
switch (enumval) {
   case MILK: lap(); break;
   case WATER: sip(); break;
   case BEER: quaff(); break;
   case OTHER: 
   default: dance(); break;
}

89voto

El siguiente es un ejemplo completo basado en JeeBee del post, el uso de java enumeración en lugar de utilizar un método personalizado.

Tenga en cuenta que en Java SE 7 y versiones posteriores, puede utilizar un objeto de Cadena en la instrucción de cambiar la expresión en su lugar.

public class Main {

    /**
    * @param args the command line arguments
    */
    public static void main(String[] args) {

      String current = args[0];
      Days currentDay = Days.valueOf(current.toUpperCase());

      switch (currentDay) {
          case MONDAY:
          case TUESDAY:
          case WEDNESDAY:
              System.out.println("boring");
              break;
          case THURSDAY:
              System.out.println("getting better");
              case FRIDAY:
          case SATURDAY:
          case SUNDAY:
              System.out.println("much better");
              break;

      }
  }

  public enum Days {

    MONDAY,
    TUESDAY,
    WEDNESDAY,
    THURSDAY,
    FRIDAY,
    SATURDAY,
    SUNDAY
  }
}

25voto

James Curran Puntos 55356

Los conmutadores basados en números enteros puede ser optimizado para muy eficiente de código. Los conmutadores basados en otro tipo de datos sólo puede ser compilado para una serie de if() declaraciones.

Por esa razón C Y C++ sólo se permiten interruptores en los tipos integer, ya que no tenía sentido con otros tipos.

Los diseñadores de C# decidió que el estilo era importante, incluso si no hubiera ninguna ventaja.

Los diseñadores de Java aparentemente pensó igual que los diseñadores de C.

18voto

DJClayworth Puntos 11288

James Curran, sucintamente, dice: "los Conmutadores basados en números enteros puede ser optimizado para muy eficiente de código. Los conmutadores basados en otro tipo de datos sólo puede ser compilado para una serie de if() declaraciones. Por esa razón C Y C++ sólo se permiten interruptores en los tipos integer, ya que no tenía sentido con otros tipos".

Mi opinión, y es sólo eso, es que tan pronto como usted comience a cambiar en no primitivas que usted necesita para comenzar a pensar acerca de "es igual a" en lugar de "==". En primer lugar, la comparación de dos cadenas pueden ser bastante largas procedimiento, agregando a los problemas de rendimiento que se mencionan arriba. En segundo lugar si no se enciende cadenas habrá demanda para la conmutación en las cadenas de ignorar caso, el cambio en las cadenas de considerar/ignorar la configuración regional,el cambio en cadenas basado en regex.... me iba a aprobar de una decisión que salvó un montón de tiempo para que el lenguaje de los desarrolladores en el costo de una pequeña cantidad de tiempo para programadores.

Iteramos.com

Iteramos es una comunidad de desarrolladores que busca expandir el conocimiento de la programación mas allá del inglés.
Tenemos una gran cantidad de contenido, y también puedes hacer tus propias preguntas o resolver las de los demás.

Powered by:

X