JavaRush /Blog Java /Random-ES /Declaración de cambio en Java

Declaración de cambio en Java

Publicado en el grupo Random-ES
Imagina que estás parado en una bifurcación, como el héroe de un cuadro famoso. Si vas a la izquierda perderás tu caballo; si vas a la derecha ganarás conocimiento. ¿Cómo programar tal situación? Lo más probable es que ya sepa que tomamos esa decisión utilizando las construcciones if-then y if-then-else .
if (turn_left) {
    System.out.println(«Коня потеряешь»);
}
if (turn_right) {
    System.out.println(“Знания обретёшь”);
}
else
    System.out.println(“Так и будешь стоять?);
¿Qué pasa si no hay dos de esas pistas, sino 10? ¿Existe un camino “a la derecha”, “un poco a la izquierda”, “un poco más a la izquierda”, etc., en la cantidad de 10 piezas? ¡ Imagínese cómo crecerá su código if-then-else en esta versión!
if (вариант1)
{}
else if (вариант2)
{}else if (вариантN).
Entonces, no tienes una bifurcación de condiciones, sino varias, digamos, 10 (lo importante aquí es que el número de bifurcaciones es limitado). Para tales situaciones, existe un operador de selección especial: switch case java .
switch (ВыражениеДляВыбора) {
           case  (Значение1):
               Код1;
               break;
           case (Значение2):
               Код2;
               break;
...
           case (ЗначениеN):
               КодN;
               break;
           default:
               КодВыбораПоУмолчанию;
               break;
       }
El orden de ejecución en el comunicado es el siguiente:
  • Se evalúa la expresión de selección. A continuación, la declaración de cambio compara la expresión resultante con el siguiente Valor (en el orden indicado).
  • Si SelectExpression coincide con el valor, entonces se ejecuta el código que sigue a los dos puntos.
  • Si se encuentra la construcción break , entonces el control se transfiere fuera del comando switch.
  • Si no se encuentran coincidencias entre ExpressionForSelection y Values, el control se transfiere a DefaultSelectionCode.
Puntos importantes
  • El tipo SelectionExpression para una declaración de selección de cambio en Java debe ser uno de los siguientes:

    • byte , corto , char , int .
    • Sus envoltorios son Byte , Short , Character , Integer .
    • Cadena (desde Java 7).
    • Enumeración ( Enum ).
  • El bloque predeterminado es opcional, luego, si SelectionExpression y Values ​​no coinciden, no se realizará ninguna acción.
  • break es opcional; si no está presente, el código continuará ejecutándose (ignorando más comparaciones de valores en bloques de casos) hasta la primera breakdeclaración de cambio encontrada o hasta el final.
  • si es necesario ejecutar el mismo código para varias opciones de selección, para evitar duplicaciones indicamos varios valores correspondientes delante en bloques de casos consecutivos .

Pasemos a la práctica de utilizar la declaración de cambio en Java.

No te preocupes, hemos terminado con la teoría y después de más ejemplos todo quedará mucho más claro. Entonces empecemos. Veamos un ejemplo de la astronomía sobre los planetas del sistema solar. De acuerdo con las últimas normas internacionales, excluiremos a Plutón (debido a las propiedades de su órbita). Recordemos que nuestros planetas están ubicados desde el Sol en la siguiente secuencia: Mercurio, Venus, Tierra, Marte, Júpiter, Saturno, Urano y Neptuno. Creemos un método Java que reciba como entrada el número de serie del planeta (relativo a la distancia al Sol) y como salida proporcione la composición principal de la atmósfera de este planeta en forma de Lista <String> . Permítanme recordarles que algunos planetas tienen una composición atmosférica similar. Así, Venus y Marte contienen principalmente dióxido de carbono, Júpiter y Saturno están compuestos por hidrógeno y helio, y Urano y Neptuno, además del último par de gases, también tienen metano. Nuestra función:
public static List<String> getPlanetAtmosphere(int seqNumberFromSun) {
    List<String> result = new ArrayList<>();
    switch (seqNumberFromSun) {
        case 1: result.add("Sin ambiente");
            break;
        case 2:
        case 4: result.add("Dióxido de carbono");
            break;
        case 3: result.add("Dióxido de carbono");
            result.add("Nitrógeno");
            result.add("Oxígeno");
            break;
        case 5:
        case 6: result.add("Hidrógeno");
            result.add("Helio");
            break;
        case 7:
        case 8: result.add("Metano");
            result.add("Hidrógeno");
            result.add("Helio");
            break;
        default:
            break;
    }
    return result;
}
Tenga en cuenta: comparamos el mismo código con planetas con composiciones atmosféricas idénticas. Y lo hicimos utilizando construcciones de casos consecutivos . Entonces, si queremos obtener la composición de la atmósfera de nuestro planeta de origen, llamamos a nuestro método con el parámetro 3:
getPlanetAtmosphere(3).
System.out.println(getPlanetAtmosphere(3)) вернет нам [Углекислый газ, Азот, Кислород].
Experimente con break ¿ Qué sucede si eliminamos todas las declaraciones de break ? Probémoslo en la práctica:
public static List<String> getPlanetAtmosphere(int seqNumberFromSun) {
    List<String> result = new ArrayList<>();
    switch (seqNumberFromSun) {
        case 1: result.add("Sin ambiente");
        case 2:
        case 4: result.add("Dióxido de carbono");
        case 3: result.add("Dióxido de carbono");
            result.add("Nitrógeno");
            result.add("Oxígeno");
        case 5:
        case 6: result.add("Hidrógeno");
            result.add("Helio");
        case 7:
        case 8: result.add("Metano");
            result.add("Hidrógeno");
            result.add("Helio");
        default:
    }
    return result;
}
Si imprimimos el resultado del método System.out.println(getPlanetAtmosphere(3)), entonces nuestro planeta de origen no será tan adecuado para la vida. ¿O adecuado? Juzgue usted mismo: [Dióxido de carbono, Nitrógeno, Oxígeno, Hidrógeno, Helio, Metano, Hidrógeno, Helio], ¿ Por qué sucedió esto? El programa ejecutó todos los casos después del primer partido y hasta el final del bloque de cambio.

Interrupción de optimización excesiva

Tenga en cuenta que podemos mejorar el método con una disposición diferente de directivas de interrupción y opciones de selección.
public static List<String> getPlanetAtmosphere(int seqNumberFromSun) {
    List<String> result = new ArrayList<>();
    switch (seqNumberFromSun) {
        case 1: result.add("Sin ambiente");
                break;
        case 3: result.add("Nitrógeno");
                result.add("Oxígeno");
        case 2:
        case 4: result.add("Dióxido de carbono");
                break;
        case 7:
        case 8: result.add("Metano");
        case 5:
        case 6: result.add("Hidrógeno");
                result.add("Helio");
    }
     return result;
}
Parece más corto, ¿no? Redujimos el número total de declaraciones jugando con el orden de los casos y reagrupándolas. Ahora cada tipo de gas se agrega a la lista en una sola línea de código. La lista del último ejemplo del método se muestra solo para demostrar el trabajo; no se recomienda escribir en ese estilo. Si el autor (y más aún los programadores externos) de un código similar tiene que mantenerlo, será muy difícil restaurar la lógica para la formación de bloques de selección y el código ejecutable para la declaración de cambio de Java.

Diferencias de si

Si bien las declaraciones if y switch son similares en apariencia , no olvide que el operador de opción múltiple switch basa la elección de las opciones de ejecución en un VALOR ESPECÍFICO, mientras que en if. puede ser cualquier expresión lógica. Tenga en cuenta este hecho al diseñar su código. Echemos un vistazo más de cerca a las innovaciones para Switch en diferentes versiones de Java.

Cambiar en Java 7

Antes de Java 7, las primitivas byte, short, char e int podían usarse como valor para un modificador. También hubo soporte para enumeraciones y contenedores de los tipos primitivos enumerados anteriormente: Carácter, Byte, Corto y Entero. ¡Pero a menudo necesitamos encontrar el valor de una cadena de cambio de Java! Así es como se vería en Java 6:
DayOfWeek day = DayOfWeek.fromValue("Thursday");

switch (day) {
  case MONDAY:
     System.out.println("Today is windy !");
     break;
  case THURSDAY:
     System.out.println("Today is sunny !");
     break;
  case WEDNESDAY:
     System.out.println("Today is rainy!");
     break;
  default:
     System.out.println("Oooops, something wrong !");
Y enumeración:
public enum DayOfWeek {
  MONDAY("Monday"),
  THURSDAY("Thursday"),
  WEDNESDAY("Wednesday"),
  NOT_FOUND("Not found");

  private final String value;

  DayOfWeek(final String value) {
     this.value = value;
  }

  public static DayOfWeek fromValue(String value) {
     for (final DayOfWeek dayOfWeek : values()) {
        if (dayOfWeek.value.equalsIgnoreCase(value)) {
           return dayOfWeek;
        }
     }
     return NOT_FOUND;
  }
}
Pero a partir de Java 7, era posible utilizar el tipo String como valor para un modificador:
String day = "Thursday";

switch (day) {
  case "Monday":
     System.out.println("Today is windy !");
     break;
  case "Thursday":
     System.out.println("Today is sunny !");
     break;
  case "Wednesday":
     System.out.println("Today is rainy!");
     break;
  default:
     System.out.println("Oooops, something wrong !");
}
A pesar de las nuevas características, el enfoque que utiliza enum es más flexible y se recomienda su uso: podemos reutilizar este enum muchas veces.

Cambiar en Java 12

Java 12 ha mejorado las expresiones Switch para la coincidencia de patrones. Si usamos Switch como en el ejemplo anterior, para establecer el valor de alguna variable, teníamos que calcular el valor y asignarlo a la variable dada, y luego usar break:
int count = 2;
int value;
switch (count) {
  case 1:
     value = 12;
     break;
  case 2:
     value = 32;
     break;
  case 3:
     value = 52;
     break;
  default:
     value = 0;
}
Pero gracias a las capacidades de Java 12, podemos reescribir esta expresión de la siguiente manera:
int value = switch (count) {
  case 1:
     break 12;
  case 2:
     break 32;
  case 3:
     break 52;
  default:
     break 0;
};
Repasemos un poco los cambios:
  1. Si anteriormente establecimos un valor de variable dentro de los bloques case, ya que la declaración switch en sí no podía devolver nada, ahora tenemos esa oportunidad y devolvemos el valor directamente usando switch.

  2. Anteriormente, ya no podíamos tener nada a la derecha de break, pero ahora lo usamos como una declaración de retorno para devolver el valor de nuestro interruptor. Los dos puntos marcan el punto de entrada a un bloque de declaración. Es decir, a partir de ese punto comienza la ejecución de todo el código siguiente, incluso cuando se encuentre otra etiqueta.

    El resultado es una transición de un extremo a otro de una marca a otra, lo que también se denomina caída .

Declaración de cambio en Java - 2Para completar dicho pase, debe revisar todos los elementos por completo o utilizar la pausa o el retorno. La innovación en Java 12 nos brinda la posibilidad de utilizar el operador lambda, lo que a su vez garantiza que solo se ejecutará el código a su derecha. Sin ningún "fracaso". ¿Cómo se verá el ejemplo anterior en este caso?
int count = 2;
int value = switch (count) {
  case 1 -> 12;
  case 2 -> 32;
  case 3 -> 52;
  default -> 0;
};
El código se ha vuelto mucho más simple, ¿no? Y una cosa más: el operador lambda también puede servir como un análogo típico de dos puntos, después del cual hay un bloque completo con algunas operaciones:
int count = 2;
int value = switch (count) {
  case 1 -> {
     //algunas operaciones computacionales...
     break 12;
  }
  case 2 -> {
     //algunas operaciones computacionales...
     break 32;
  }
  case 3 -> {
     //algunas operaciones computacionales...
     break 52;
  }
  default -> {
     //algunas operaciones computacionales...
     break 0;
  }
};
Bueno, ¿qué pasa si en algunos casos el valor de retorno es el mismo? Resulta que en realidad tenemos los mismos casos para algunos valores diferentes. Así es como esto podría acortarse usando nuevas funciones en Java 12:
int count = 2;
int value = switch (count) {
  case 1, 3, 5 -> 12;
  case 2, 4, 6 -> 52;
  default -> 0;
};

Cambiar en Java 13

En Java 13, la forma en que un modificador devuelve un valor ha cambiado. Si en java 12 escribimos el valor de retorno después de la interrupción, que nos sirvió como retorno para el bloque de cambio, ahora devolveremos el valor usando la palabra rendimiento . Miremos:
int value = switch (count) {
  case 1:
     yield 12;
  case 2:
     yield 32;
  case 3:
     yield 52;
  default:
     yield 0;
};
Al mismo tiempo, el código escrito en Java 12 que usa break to return no se compilará (( Declaración de cambio en Java - 3se usará Break, pero en situaciones en las que no necesitamos devolver nada.

Total

  • Utilice la declaración case cuando haya más de dos ramas para evitar saturar su código con estructuras if.
  • No olvide finalizar el bloque lógico de cada rama correspondiente a un valor específico (bloque de caso) con una llamada de interrupción .
  • Además de algunos tipos primitivos, la declaración de cambio también puede usar los tipos Enum y String como expresiones .
  • Recuerde el bloque predeterminado : utilícelo para manejar valores de selección no planificados.
  • Para optimizar el rendimiento, mueva las ramas de código con las opciones más comunes al principio del bloque de cambio.
  • No se deje llevar por la "optimización" eliminando la pausa al final del bloque de selección de casos ; dicho código es difícil de entender y, como resultado, difícil de mantener durante su desarrollo.
Comentarios
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION