Instrução Java Switch

Instrução Java Switch

1. Visão geral

Neste tutorial, aprenderemos o que é a instruçãoswitch e como usá-la.

A instruçãoswitch nos permite substituir várias construçõesif-else aninhadas e, assim, melhorar a legibilidade de nosso código.

Switch evoluiu com o tempo - novos tipos suportados foram adicionados, particularmente em Java 5 e 7. Além disso, ele continua a evoluir - expressõesswitch provavelmente serão introduzidas no Java 12.

A seguir, daremos alguns exemplos de código para demonstrar o uso da instruçãoswitch, a função da instruçãobreak, os requisitos para os valores de argumentoswitch /case e a comparação deStrings na instruçãoa switch.

Vamos passar para o exemplo.

2. Exemplo de Uso

Digamos que temos as seguintes instruçõesif-else aninhadas:

public String exampleOfIF(String animal) {
    String result;
    if (animal.equals("DOG") || animal.equals("CAT")) {
        result = "domestic animal";
    } else if (animal.equals("TIGER")) {
        result = "wild animal";
    } else {
        result = "unknown animal";
    }
    return result;
}

O código acima não parece bom e seria difícil de manter e raciocinar sobre ele. Para melhorar a legibilidade, poderíamos usar uma instruçãoswitch aqui:

public String exampleOfSwitch(String animal) {
    String result;
    switch (animal) {
        case "DOG":
            result = "domestic animal";
            break;
        case "CAT":
            result = "domestic animal";
            break;
        case "TIGER":
            result = "wild animal";
            break;
        default:
            result = "unknown animal";
            break;
    }
    return result;
}

Conforme mostrado acima, comparamos o argumentoswitchanimal com os diversos valorescase. Se nenhum dos valorescase for igual ao argumento, então o bloco sob o rótulodefault é executado.

Simplificando, a instruçãobreak é usada para sair de uma instruçãoswitch.

3. A declaraçãobreak

Embora a maioria das instruçõesswitch na vida real implique que apenas um dos blocoscase deve ser executado, a instruçãothe break é necessária para sair deswitch após a conclusão do bloco.

Se esquecermos de escrever umbreak, os blocos abaixo serão executados.

Para demonstrar isso, vamos omitir as instruçõesbreak e adicionar a saída ao console para cada bloco:

public String forgetBreakInSwitch(String animal) {
    switch (animal) {
    case "DOG":
        System.out.println("domestic animal");
    default:
        System.out.println("unknown animal");
    }
}

Vamos executar este códigoforgetBreakInSwitch (“DOG”),e verificar a saída para provar que todos os blocos foram executados:

domestic animal
unknown animal

Portanto, devemos ter cuidado e adicionar instruçõesbreak no final de cada bloco, a menos que haja necessidade de passar para o código no próximo rótulo.

O único bloco em quebreak não é necessário é o último, mas adicionarbreak ao último bloco torna o código menos sujeito a erros.

Também podemos aproveitar esse comportamento paraomit break when we want the same code executed for several case statements.. Vamos reescrever o exemplo da seção anterior agrupando os 2 primeiros casos:

public String exampleOfSwitch(String animal) {
    String result;
    switch (animal) {
        case "DOG":
        case "CAT":
            result = "domestic animal";
            break;
        case "TIGER":
            result = "wild animal";
            break;
        default:
            result = "unknown animal";
            break;
    }
    return result;
}

4. Argumentoswitch e valorescase

Agora vamos discutir os tipos permitidos de argumentoswitch e valorescase, os requisitos para eles e como a instruçãoswitch funciona com Strings.

4.1. Tipos de dados

Não podemos comparar todos os tipos de objetos e primitivos na instruçãoswitch. A switch works only with four primitives and their wrappers, as well as with the enum type and the String class:

  • byte eByte

  • short eShort

  • int eInteger

  • char eCharacter

  • enum

  • Corda

O tipoString está disponível na instruçãoswitch começando com Java 7.

O tipoenum foi introduzido no Java 5 e está disponível na instruçãoswitch desde então.

As classes de wrapper também estão disponíveis desde o Java 5.

Obviamente, o argumentoswitche os valorescase devem ser do mesmo tipo.

4.2. No null Values

We can’t pass the null value as an argument to a switch statement. Se fizermos isso, o programa irá lançarNullPointerException, usando nosso primeiroswitch example:

@Test(expected=NullPointerException.class)
public void whenSwitchAgumentIsNull_thenNullPointerException() {
    String animal = null;
    Assert.assertEquals("domestic animal", s.exampleOfSwitch(animal));
}

Claro, não podemos passarnull como um valor para o rótulocase de uma instruçãoswitch. Se fizermos isso, o código não será compilado.

4.3. Valores deCase como constantes de tempo de compilação

Se tentarmos substituir o valor do casoDOG pela variáveldog , o código não será compilado até que marquemos a variáveldog comofinal:

final String dog="DOG";
String cat="CAT";

switch (animal) {
case dog: //compiles
    result = "domestic animal";
case cat: //does not compile
    result = "feline"
}

4.4. String Comparação

Se uma instruçãoswitch usasse o operador de igualdade para comparar strings, não poderíamos comparar um argumentoString criado com o operadornew para um valor de casoString corretamente.

Felizmente, oswitch operator uses the equals() method under the hood.

Vamos demonstrar isso:

@Test
public void whenCompareStrings_thenByEqual() {
    String animal = new String("DOG");
    assertEquals("domestic animal", s.exampleOfSwitch(animal));
}

5. Nova expressãoswitch

Java 12 está disponível e com ele a visualização de um novo recurso - uma expressãoswitch menos detalhada.

Para habilitá-lo, precisamos passar–enable-preview para o compilador.

Vamos dar uma olhada:

var month = JUN;
var value = switch(month) {
  case JAN, JUN, JUL -> 3;
  case FEB, SEP, OCT, NOV, DEC -> 1;
  case MAR, MAY, APR, AUG -> 2;
};

System.out.println(value); // 3

Para aproveitar a nova sintaxe, não usamos mais dois pontos, mas o operador conhecido nas Lambda Expressions. Observe a falta da palavra-chavebreak e que os casos de falha não estão acontecendo.

Mas ainda há a possibilidade de obter controle refinado sobre o que está acontecendo no lado direito da expressão usando blocos de código. Nesse caso, precisamosbreak manualmente e especificar um valor de retorno:

public static void switchLocalVariable() {
    var month = Month.AUG;
    int i = switch (month){
        case JAN,JUN, JUL -> 3;
        case FEB,SEP, OCT, NOV, DEC -> 1;
        case MAR,MAY, APR, AUG -> {
            int j = month.toString().length() * 4;
            break j;
        }
    };
    System.out.println(i); //12
}

6. Conclusão

Neste tutorial, aprendemos as sutilezas do uso da instruçãoswitch em Java. Podemos decidir se usarswitch  com base na legibilidade e no tipo dos valores comparados.

A instrução switch é um bom candidato para casos em que temos um número limitado de opções em um conjunto predefinido (por exemplo: dias da semana). Caso contrário, teríamos que modificar o código cada vez que um novo valor fosse adicionado ou removido, o que pode não ser viável. Para esses casos, devemos considerar outras abordagens, comopolymorphism ou outros padrões de design comoCommand.

Como sempre, o código completo está disponívelover on GitHub.