Usar dos valores para una declaración de caso de cambio

296

En mi código, el programa hace algo dependiendo del texto ingresado por el usuario. Mi código se ve así:

switch (name) {
        case text1: {
            //blah
            break;
        }
        case text2: {
            //blah
            break;
        }
        case text3: {
            //blah
            break;
        }
        case text4: {
            //blah
            break;
        }

Sin embargo, el código dentro de los casos text1 y text4es el mismo. Por lo tanto, me preguntaba si sería posible implementar algo como

case text1||text4: {
            //blah
            break;
        }

Yo se que el || operador no funcionará en la declaración del caso, pero ¿hay algo similar que pueda usar?

Ankush
fuente
32
Ser una pregunta básica hace que sea más elegible para votos a favor si no es un duplicado, ya que es muy útil. Y es algo que no se me ocurrió lo más posible, pero ahora que me doy cuenta de que es cegadoramente obvio. En resumen, un Q&A bastante impresionante
Richard Tingle
1
@RichardTingle - ¿Está familiarizado con el dispositivo de Duff - en.wikipedia.org/wiki/Duff%27s_device
user93353
44
"¿Por qué tantos votos a favor? Busque" java switch "en Internet y lea una de las mil explicaciones". <- ¿Qué crees que estaba haciendo?
Brendan
44
Literalmente busqué "casos múltiples en una línea de Java" y este Q&A fue el primer resultado.
domenix
1
La demostración del interruptor en la respuesta seleccionada podría reformularse ahora que JDK-12 ha integrado JEP-325. :)
Naman

Respuestas:

556

Puede usar tener ambas CASEdeclaraciones de la siguiente manera.

  case text1: 
  case text4:{
            //blah
            break;
        }

VER ESTE EJEMPLO: El ejemplo de código calcula la cantidad de días en un mes en particular:

class SwitchDemo {
    public static void main(String[] args) {

        int month = 2;
        int year = 2000;
        int numDays = 0;

        switch (month) {
            case 1:
            case 3:
            case 5:
            case 7:
            case 8:
            case 10:
            case 12:
                numDays = 31;
                break;
            case 4:
            case 6:
            case 9:
            case 11:
                numDays = 30;
                break;
            case 2:
                if (((year % 4 == 0) && 
                     !(year % 100 == 0))
                     || (year % 400 == 0))
                    numDays = 29;
                else
                    numDays = 28;
                break;
            default:
                System.out.println("Invalid month.");
                break;
        }
        System.out.println("Number of Days = "
                           + numDays);
    }
}

Este es el resultado del código:

Number of Days = 29

CAER A TRAVÉS:

Otro punto de interés es la declaración de ruptura. Cada declaración de interrupción termina la declaración del interruptor de cierre. El flujo de control continúa con la primera instrucción que sigue al bloque del interruptor. Las declaraciones de interrupción son necesarias porque sin ellas, las declaraciones en bloques de conmutación fall through: todas las declaraciones después de la etiqueta de caso coincidente se ejecutan en secuencia, independientemente de la expresión de las etiquetas de caso posteriores, hasta que se encuentra una declaración de interrupción.

CÓDIGO DE EJEMPLO:

public class SwitchFallThrough {

    public static void main(String[] args) {
        java.util.ArrayList<String> futureMonths =
            new java.util.ArrayList<String>();

        int month = 8;

        switch (month) {
            case 1:  futureMonths.add("January");
            case 2:  futureMonths.add("February");
            case 3:  futureMonths.add("March");
            case 4:  futureMonths.add("April");
            case 5:  futureMonths.add("May");
            case 6:  futureMonths.add("June");
            case 7:  futureMonths.add("July");
            case 8:  futureMonths.add("August");
            case 9:  futureMonths.add("September");
            case 10: futureMonths.add("October");
            case 11: futureMonths.add("November");
            case 12: futureMonths.add("December");
            default: break;
        }

        if (futureMonths.isEmpty()) {
            System.out.println("Invalid month number");
        } else {
            for (String monthName : futureMonths) {
               System.out.println(monthName);
            }
        }
    }
}

Este es el resultado del código:

August
September
October
November
December

Usar cadenas en declaraciones de conmutador

En Java SE 7 y versiones posteriores, puede usar un objeto String en la expresión de la instrucción switch. El siguiente ejemplo de código, muestra el número del mes en función del valor de la cadena denominada mes:

public class StringSwitchDemo {

    public static int getMonthNumber(String month) {

        int monthNumber = 0;

        if (month == null) {
            return monthNumber;
        }

        switch (month.toLowerCase()) {
            case "january":
                monthNumber = 1;
                break;
            case "february":
                monthNumber = 2;
                break;
            case "march":
                monthNumber = 3;
                break;
            case "april":
                monthNumber = 4;
                break;
            case "may":
                monthNumber = 5;
                break;
            case "june":
                monthNumber = 6;
                break;
            case "july":
                monthNumber = 7;
                break;
            case "august":
                monthNumber = 8;
                break;
            case "september":
                monthNumber = 9;
                break;
            case "october":
                monthNumber = 10;
                break;
            case "november":
                monthNumber = 11;
                break;
            case "december":
                monthNumber = 12;
                break;
            default: 
                monthNumber = 0;
                break;
        }

        return monthNumber;
    }

    public static void main(String[] args) {

        String month = "August";

        int returnedMonthNumber =
            StringSwitchDemo.getMonthNumber(month);

        if (returnedMonthNumber == 0) {
            System.out.println("Invalid month");
        } else {
            System.out.println(returnedMonthNumber);
        }
    }
}

La salida de este código es 8.

DE Java Docs

PSR
fuente
oh ok Eso fue fácil. No sabía que podía hacer eso
Ankush
18
Vale la pena mencionar que esta característica del lenguaje se llama fallthrough. Los casos sin breakse añaden básicamente con el siguiente bloque de casos que está visualmente debajo, por lo tanto se caen .
Emperador Orionii
55
@ Kobor42 primero aprende a hablar en sitios públicos. De cualquier forma que tu sugerencia sea útil. Gracias
PSR
1
@ Kobor42 ¿Qué tal? ¿Por qué has usado ese formato? Poner casos horizontalmente hace que el código sea menos legible y generalmente se considera una mala práctica [Referencia opcional pero deseada]. Siempre he sentido que las declaraciones de cambio son un formato particularmente legible, pero presentado de esta manera pierden todo eso.
Richard Tingle
2
La demostración del interruptor podría reformularse ahora que JDK-12 ha integrado JEP-325. :)
Naman
27

Los casevalores son simplemente puntos "goto" sin código que pueden compartir el mismo punto de entrada:

case text1:
case text4: 
    //blah
    break;

Tenga en cuenta que las llaves son redundantes.

Bohemio
fuente
@trig lol. Últimamente estoy haciendo ese tipo de cosas, culpando a la mecanografía de iPhone con el pulgar. Saludos
Bohemio
21

Solo haz

case text1: case text4: 
     do stuff;
     break;
kaljak
fuente
15

Con la integración de JEP 325: Expresiones de conmutador (Vista previa) en las compilaciones de acceso temprano de JDK-12, ahora se puede utilizar la nueva forma de la etiqueta del conmutador como:

case text1, text4 -> {
     //blah
} 

o para reformular la demostración de una de las respuestas , algo como: -

public class RephraseDemo {

    public static void main(String[] args) {
        int month = 9;
        int year = 2018;
        int numDays = 0;

        switch (month) {
            case 1, 3, 5, 7, 8, 10, 12 ->{
                numDays = 31;
            }
            case 4, 6, 9, 11 ->{
                numDays = 30;
            }
            case 2 ->{
                if (((year % 4 == 0) &&
                        !(year % 100 == 0))
                        || (year % 400 == 0))
                    numDays = 29;
                else
                    numDays = 28;
            }
            default ->{
                System.out.println("Invalid month.");

            }
        }
        System.out.println("Number of Days = " + numDays);
    }
}

Así es como puede probarlo: compile una función de vista previa JDK12 con Maven

Naman
fuente
6

Los corchetes son innecesarios. Solo haz

case text1:
case text4:
  doSomethingHere();
  break;
case text2:
  doSomethingElse()
  break;

Si alguien tiene curiosidad, esto se llama un caso fallido. La capacidad de hacer esto es la razón por la cual break;es necesario finalizar las declaraciones de casos. Para obtener más información, consulte el artículo de wikipedia http://en.wikipedia.org/wiki/Switch_statement .

scottmrogowski
fuente
5

Las fallthroughrespuestas de otros son buenas.

Sin embargo, otro enfoque sería extraer métodos del contenido de las declaraciones de su caso y luego simplemente llamar al método apropiado de cada caso.

En el siguiente ejemplo, tanto el caso 'text1' como el caso 'text4' se comportan igual:

switch (name) {
        case text1: {
            method1();
            break;
        }
        case text2: {
            method2();
            break;
        }
        case text3: {
            method3();
            break;
        }
        case text4: {
            method1();
            break;
        }

Personalmente, creo que este estilo de redacción de declaraciones de casos es más fácil de mantener y un poco más legible, especialmente cuando los métodos que llama tienen buenos nombres descriptivos.

Colin D
fuente
1
No es más fácil de mantener si text1ytext4 fácil de casi CIERTAMENTE hará lo mismo, independientemente de un cambio futuro. Si siempre deben estar vinculados, hacer un cambio en el caso de text1(es decir, cambiar el método al que llama) requeriría un cambio text4. En este caso, obviamente no es más fácil de mantener. Depende de la situación.
Nick Freeman
1
Diré que este método probablemente debería combinarse con la otra manera de todos modos, ya que las declaraciones de interruptor no son (en mi humilde opinión) la estructura de programación más bonita.
Nick Freeman
5

El enfoque fallido es el mejor que siento.

case text1:
case text4: {
        //Yada yada
        break;
} 
Ankur Sharma
fuente
5

Puedes usar:

case text1: case text4: 
     do stuff;
     break;
Joseph DSCS
fuente
4

Los valores de los casos son simplemente puntos "goto" sin código que pueden compartir el mismo punto de entrada:

case text1:
case text4: {
// Hacer algo se
rompe;
}

Tenga en cuenta que las llaves son redundantes.

David_DD
fuente
1

JEP 354: Expresiones de cambio (Vista previa) en JDK-13 y JEP 361: Expresiones de cambio (Estándar) en JDK-14 extenderá la declaración de cambio para que pueda usarse como una expresión .

Ahora usted puede:

  • Asigna directamente la variable desde la expresión del interruptor ,
  • use una nueva forma de etiqueta de interruptor ( case L ->):

    El código a la derecha de una etiqueta de interruptor "caso L ->" está restringido a ser una expresión, un bloque o (por conveniencia) una instrucción throw.

  • use múltiples constantes por caso, separadas por comas,
  • y tampoco hay más saltos de valor :

    Para obtener un valor de una expresión de cambio, la breakdeclaración with value se descarta a favor de una yielddeclaración.

Entonces, la demostración de una de las respuestas podría verse así:

public class SwitchExpression {

  public static void main(String[] args) {
      int month = 9;
      int year = 2018;
      int numDays = switch (month) {
        case 1, 3, 5, 7, 8, 10, 12 -> 31;
        case 4, 6, 9, 11 -> 30;
        case 2 -> {
          if (java.time.Year.of(year).isLeap()) {
            System.out.println("Wow! It's leap year!");
            yield 29;
          } else {
            yield 28;
          }
        }
        default -> {
          System.out.println("Invalid month.");
          yield 0;
        }
      };
      System.out.println("Number of Days = " + numDays);
  }
}
Iskuskov Alexander
fuente