Usando dois valores para uma instrução de caso de switch


296

No meu código, o programa faz algo dependendo do texto digitado pelo usuário. Meu código se parece com:

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

No entanto, o código dentro de casos text1e text4é o mesmo. Fiquei, portanto, imaginando se seria possível implementar algo como

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

Sei que o ||operador não funcionará na declaração de caso, mas há algo semelhante que posso usar.


32
Sendo uma pergunta básica, torna-se mais elegível para votos positivos, se não for uma duplicata, pois é amplamente útil. E é algo que não me ocorreu como possível, mas agora que percebo que é cegamente óbvio. Portanto, tudo somado um Q bastante impressionante & A
Richard Tingle

1
@RichardTingle - você está familiarizado com dispositivos de Duff - en.wikipedia.org/wiki/Duff%27s_device
user93353

4
"Por que tantos votos positivos? Pesquise" java switch "na internet e leia uma das mil explicações." <- o que você acha que eu estava fazendo?
Brendan

4
Eu literalmente procurei por "vários casos em uma linha java" e este Q&A foi o primeiro resultado.
domenix 5/09/16

1
A demonstração do switch na resposta selecionada pode ser reformulada agora que o JDK-12 integrou o JEP-325. :)
Naman

Respostas:


556

Você pode usar as duas CASEinstruções da seguinte maneira.

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

VEJA ESTE EXEMPLO: O exemplo de código calcula o número de dias em um mês específico:

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);
    }
}

Esta é a saída do código:

Number of Days = 29

CAIR EM:

Outro ponto de interesse é a declaração de quebra. Cada instrução de interrupção encerra a instrução de chave anexa. O fluxo de controle continua com a primeira instrução após o bloco do interruptor. As instruções de interrupção são necessárias porque, sem elas, as instruções nos blocos de chave fall through: Todas as instruções após o rótulo do caso correspondente são executadas em sequência, independentemente da expressão dos rótulos de caso subsequentes, até que seja encontrada uma declaração de interrupção.

CÓDIGO DO EXEMPLO:

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);
            }
        }
    }
}

Esta é a saída do código:

August
September
October
November
December

Usando seqüências de caracteres nas instruções do switch

No Java SE 7 e posterior, você pode usar um objeto String na expressão da instrução switch. O exemplo de código a seguir, exibe o número do mês com base no valor da String denominada month:

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);
        }
    }
}

A saída deste código é 8.

DO Java Docs


Ah ok. Essa foi fácil. Não sabia que eu poderia fazer isso
Ankush

18
Vale ressaltar que esse recurso de idioma é chamado de avanço. Casos sem breaksão basicamente anexados ao próximo bloco de caso, que é visualmente abaixo, e portanto cai .
Imperador Orionii 23/05

5
@ Kobor42 primeiro aprender a falar em público sites.Any como sua sugestão é ajudar ful.Thanks
PSR

1
@ Kobor42 Que tal: Por que você usou essa formatação? Colocar casos horisontalmente torna o código menos legível e geralmente é considerado uma má prática [Referência opcional, mas desejada]. Eu sempre achei que as instruções do switch são um formato particularmente legível, mas, dessa forma, elas perdem tudo isso.
Richard Tingle

2
A demonstração do switch pode ser reformulada agora que o JDK-12 integrou o JEP-325. :)
Naman


27

Os casevalores são apenas pontos "ir" sem código que podem compartilhar o mesmo ponto de entrada:

case text1:
case text4: 
    //blah
    break;

Observe que os chavetas são redundantes.


@trig lol. Ultimamente, estou fazendo esse tipo de coisa - culpando a digitação do polegar do iPhone. Cheers
Bohemian

21

Apenas faça

case text1: case text4: 
     do stuff;
     break;

15

Com a integração do JEP 325: Expressões de switch (visualização) nas compilações de acesso antecipado do JDK-12, agora é possível fazer uso da nova forma do rótulo do switch como: -

case text1, text4 -> {
     //blah
} 

ou reformular a demonstração de uma das respostas , 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);
    }
}

Aqui está como você pode tentar - Compile um recurso de visualização do JDK12 com o Maven


6

Os suportes são desnecessários. Apenas faça

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

Se alguém estiver curioso, isso é chamado de explicação do caso. A capacidade de fazer isso é o motivo pelo qual break;é necessário encerrar as declarações de caso. Para mais informações, consulte o artigo da wikipedia http://en.wikipedia.org/wiki/Switch_statement .


5

As fallthroughrespostas dos outros são boas.

No entanto, outra abordagem seria extrair métodos do conteúdo de suas instruções de caso e chamar o método apropriado de cada caso.

No exemplo abaixo, o caso 'texto1' e o caso 'texto4' se comportam da mesma maneira:

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

Pessoalmente, acho esse estilo de escrever declarações de caso mais sustentável e um pouco mais legível, especialmente quando os métodos que você chama possuem bons nomes descritivos.


1
Não é mais sustentável se text1e text4QUASE CERTAMENTE fará a mesma coisa, independentemente de uma mudança futura. Se eles sempre deveriam estar vinculados, fazer uma alteração no caso de text1(significando alterar qual método ele chama) exigiria uma alteração text4. Nesse caso, obviamente não é mais sustentável. Depende da situação.
Nick Freeman

1
Eu direi que esse método provavelmente deve ser combinado com o contrário, já que as instruções do switch não são (IMHO) a estrutura de programação mais bonita.
Nick Freeman

5

Abordar a abordagem é a melhor que eu sinto.

case text1:
case text4: {
        //Yada yada
        break;
} 


4

Os valores de caso são apenas pontos "ir" codificados que podem compartilhar o mesmo ponto de entrada:

case text1:
case text4: {
// Faça algo
quebrar;
}

Observe que os chavetas são redundantes.


1

O JEP 354: Expressões do switch (visualização) no JDK-13 e o JEP 361: Expressões do switch (padrão) no JDK-14 estenderão a instrução switch para que ele possa ser usado como expressão .

Agora você pode:

  • atribuir diretamente variável da expressão do comutador ,
  • use uma nova forma de etiqueta de chave ( case L ->):

    O código à direita de um rótulo de opção "case L ->" é restrito a ser uma expressão, um bloco ou (por conveniência) uma instrução throw.

  • use várias constantes por caso, separadas por vírgulas,
  • e também não há mais quebras de valor :

    Para gerar um valor a partir de uma expressão de opção, a breakinstrução with value é descartada em favor de uma yieldinstrução.

Portanto, a demonstração de uma das respostas pode ser assim:

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);
  }
}
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.