JavaRush /Blogue Java /Random-PT /Instrução switch em Java

Instrução switch em Java

Publicado no grupo Random-PT
Imagine que você está em uma bifurcação, como um herói de uma pintura famosa. Se você for para a esquerda, perderá seu cavalo; se for para a direita, ganhará conhecimento. Como programar tal situação? Você provavelmente já sabe que fazemos essa escolha usando construções if-then e if-then-else .
if (turn_left) {
    System.out.println(«Коня потеряешь»);
}
if (turn_right) {
    System.out.println(“Знания обретёшь”);
}
else
    System.out.println(“Так и будешь стоять?);
E se não houver duas dessas faixas, mas 10? Existe um caminho “para a direita”, “um pouco para a esquerda”, “um pouco mais para a esquerda” e assim por diante, no valor de 10 peças? Imagine como o seu código if-then-else crescerá nesta versão!
if (вариант1)
{}
else if (вариант2)
{}else if (вариантN).
Então, você não tem uma bifurcação de condições, mas várias, digamos, 10 (o importante aqui é que o número de bifurcações é limitado). Para tais situações, existe um operador de seleção especial - switch case java .
switch (ВыражениеДляВыбора) {
           case  (Значение1):
               Код1;
               break;
           case (Значение2):
               Код2;
               break;
...
           case (ЗначениеN):
               КодN;
               break;
           default:
               КодВыбораПоУмолчанию;
               break;
       }
A ordem de execução na instrução é a seguinte:
  • A SelectionExpression é avaliada. A seguir, a instrução switch compara a expressão resultante com o próximo valor (na ordem listada).
  • Se SelectExpression corresponder ao Valor, o código após os dois pontos será executado.
  • Se a construção break for encontrada , o controle será transferido para fora do comando switch.
  • Se nenhuma correspondência entre ExpressionForSelection e Values ​​for encontrada, o controle será transferido para DefaultSelectionCode.
Pontos importantes
  • O tipo SelectionExpression para uma instrução de seleção switch em Java deve ser um dos seguintes:

    • byte , curto , char , int .
    • Seus wrappers são Byte , Short , Character , Integer .
    • String (desde Java 7).
    • Enumeração ( Enum ).
  • O bloco padrão é opcional, então se SelectionExpression e Values ​​​​não corresponderem, nenhuma ação será executada.
  • break é opcional; se não estiver presente, o código continuará em execução (ignorando futuras comparações de valores em blocos case) até a primeira breakinstrução switch encontrada ou até o final.
  • se for necessário executar o mesmo código para várias opções de seleção, para evitar duplicação indicamos vários valores correspondentes na frente dele em blocos de casos consecutivos .

Vamos passar para a prática de usar a instrução switch em Java

Não se preocupe, terminamos a teoria e depois de mais exemplos tudo ficará muito mais claro. Então vamos começar. Vejamos um exemplo da astronomia sobre os planetas do sistema solar. De acordo com os mais recentes regulamentos internacionais, excluiremos Plutão (devido às propriedades da sua órbita). Lembremos que nossos planetas estão localizados a partir do Sol na seguinte sequência: Mercúrio, Vênus, Terra, Marte, Júpiter, Saturno, Urano e Netuno. Vamos criar um método Java que receba como entrada o número de série do planeta (relativo à distância do Sol), e como saída produza a composição principal da atmosfera deste planeta na forma de uma List <String> . Deixe-me lembrá-lo de que alguns planetas têm uma composição atmosférica semelhante. Assim, Vênus e Marte contêm principalmente dióxido de carbono, Júpiter e Saturno consistem em hidrogênio e hélio, e Urano e Netuno, além do último par de gases, também possuem metano. Nossa função:
public static List<String> getPlanetAtmosphere(int seqNumberFromSun) {
    List<String> result = new ArrayList<>();
    switch (seqNumberFromSun) {
        case 1: result.add("No Atmosphere");
            break;
        case 2:
        case 4: result.add("Carbon dioxide");
            break;
        case 3: result.add("Carbon dioxide");
            result.add("Nitrogen");
            result.add("Oxygen");
            break;
        case 5:
        case 6: result.add("Hydrogen");
            result.add("Helium");
            break;
        case 7:
        case 8: result.add("Methane");
            result.add("Hydrogen");
            result.add("Helium");
            break;
        default:
            break;
    }
    return result;
}
Observação: comparamos o mesmo código com planetas com composições atmosféricas idênticas. E fizemos isso usando construções de casos consecutivos . Então, se quisermos obter a composição da atmosfera do nosso planeta natal, chamamos nosso método com parâmetro 3:
getPlanetAtmosphere(3).
System.out.println(getPlanetAtmosphere(3)) вернет нам [Углекислый газ, Азот, Кислород].
Experimente o break O que acontece se removermos todas as instruções break ? Vamos tentar na prática:
public static List<String> getPlanetAtmosphere(int seqNumberFromSun) {
    List<String> result = new ArrayList<>();
    switch (seqNumberFromSun) {
        case 1: result.add("No Atmosphere");
        case 2:
        case 4: result.add("Carbon dioxide");
        case 3: result.add("Carbon dioxide");
            result.add("Nitrogen");
            result.add("Oxygen");
        case 5:
        case 6: result.add("Hydrogen");
            result.add("Helium");
        case 7:
        case 8: result.add("Methane");
            result.add("Hydrogen");
            result.add("Helium");
        default:
    }
    return result;
}
Se imprimirmos o resultado do método System.out.println(getPlanetAtmosphere(3)), nosso planeta natal não será tão adequado para a vida. Ou adequado? Julgue por si mesmo: [Dióxido de carbono, Nitrogênio, Oxigênio, Hidrogênio, Hélio, Metano, Hidrogênio, Hélio], Por que isso aconteceu? O programa executou todos os casos após a primeira partida e até o final do bloco switch.

Quebra excessiva de otimização

Observe que podemos melhorar o método com um arranjo diferente de diretivas de interrupção e opções de seleção
public static List<String> getPlanetAtmosphere(int seqNumberFromSun) {
    List<String> result = new ArrayList<>();
    switch (seqNumberFromSun) {
        case 1: result.add("No Atmosphere");
                break;
        case 3: result.add("Nitrogen");
                result.add("Oxygen");
        case 2:
        case 4: result.add("Carbon dioxide");
                break;
        case 7:
        case 8: result.add("Methane");
        case 5:
        case 6: result.add("Hydrogen");
                result.add("Helium");
    }
     return result;
}
Parece mais curto, não é? Reduzimos o número total de declarações brincando com a ordem e o reagrupamento dos casos . Agora cada tipo de gás é adicionado à lista em apenas uma linha de código. A listagem do último exemplo do método é mostrada apenas para demonstrar o trabalho; não é altamente recomendável escrever nesse estilo. Se o autor (e ainda mais os programadores terceirizados) de um código semelhante tiver que mantê-lo, será muito difícil restaurar a lógica para a formação de blocos de seleção e o código executável para a instrução java switch.

Diferenças de se

Embora as instruções if e switch sejam semelhantes em aparência , não esqueça que o operador de múltipla escolha switch baseia a escolha das opções de execução em um VALOR ESPECÍFICO, enquanto em if. pode ser qualquer expressão lógica. Leve esse fato em consideração ao projetar seu código. Vamos dar uma olhada mais de perto nas inovações para switch em diferentes versões do Java.

Mudar no Java 7

Antes do Java 7, as primitivas byte, short, char e int podiam ser usadas como valor para um switch. Também havia suporte para enum e wrappers dos tipos primitivos listados acima: Character, Byte, Short e Integer. Mas muitas vezes precisamos encontrar o valor de uma string de switch java! Seria assim no 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 !");
E enum:
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;
  }
}
Mas a partir do Java 7, foi possível usar o tipo String como valor para um switch:
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 !");
}
Apesar dos novos recursos, a abordagem usando enum é mais flexível e é recomendada para uso: podemos reutilizar esse enum muitas vezes.

Mudar no Java 12

Java 12 melhorou as expressões Switch para correspondência de padrões. Se usarmos Switch como no exemplo acima, para definir o valor de alguma variável, tivemos que calcular o valor e atribuí-lo à variável dada, e então 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;
}
Mas graças aos recursos do Java 12, podemos reescrever esta expressão da seguinte forma:
int value = switch (count) {
  case 1:
     break 12;
  case 2:
     break 32;
  case 3:
     break 52;
  default:
     break 0;
};
Vamos repassar um pouco as mudanças:
  1. Se anteriormente definimos um valor variável dentro de blocos case, já que a instrução switch em si não poderia retornar nada, agora temos essa oportunidade e retornamos o valor diretamente usando switch.

  2. Anteriormente, não podíamos mais ter nada à direita do break, mas agora usamos isso como uma instrução return para retornar o valor do nosso switch. Os dois pontos marcam o ponto de entrada em um bloco de instruções. Ou seja, a partir desse ponto começa a execução de todo o código abaixo, mesmo quando outro rótulo for encontrado.

    O resultado é uma transição ponta a ponta de marca para marca, também chamada de fall -through.

Instrução switch em Java - 2Para completar tal passagem, você deve percorrer todos os elementos completamente ou usar break ou return. A inovação no java 12 nos dá a capacidade de usar o operador lambda, que por sua vez garante que apenas o código à direita dele será executado. Sem qualquer “fracasso”. Como ficará o exemplo anterior neste caso:
int count = 2;
int value = switch (count) {
  case 1 -> 12;
  case 2 -> 32;
  case 3 -> 52;
  default -> 0;
};
O código ficou muito mais simples, não é? E mais uma coisa: o operador lambda também pode servir como um análogo típico de dois pontos, após o qual há um bloco inteiro com algumas operações:
int count = 2;
int value = switch (count) {
  case 1 -> {
     //some computational operations...
     break 12;
  }
  case 2 -> {
     //some computational operations...
     break 32;
  }
  case 3 -> {
     //some computational operations...
     break 52;
  }
  default -> {
     //some computational operations...
     break 0;
  }
};
Bem, e se em alguns casos o valor de retorno for o mesmo? Acontece que na verdade temos os mesmos casos para alguns valores diferentes. Veja como isso pode ser reduzido usando novos recursos no Java 12:
int count = 2;
int value = switch (count) {
  case 1, 3, 5 -> 12;
  case 2, 4, 6 -> 52;
  default -> 0;
};

Mudar no Java 13

No Java 13, a forma como um switch retorna um valor mudou. Se em java 12 escrevemos o valor de retorno após o break, que serviu de retorno para nós para o bloco switch, agora retornaremos o valor usando a palavra yield . Vamos olhar:
int value = switch (count) {
  case 1:
     yield 12;
  case 2:
     yield 32;
  case 3:
     yield 52;
  default:
     yield 0;
};
Ao mesmo tempo, o código escrito em java 12 usando break para retornar não será compilado (( Instrução switch em Java - 3Break será usado, mas em situações em que não precisamos retornar nada.

Total

  • Use a instrução case quando houver mais de duas ramificações para evitar sobrecarregar seu código com estruturas if.
  • Não se esqueça de finalizar o bloco lógico de cada ramificação correspondente a um valor específico (bloco case) com uma chamada break .
  • Além de alguns tipos primitivos, a instrução switch também pode usar os tipos Enum e String como expressões .
  • Lembre-se do bloco padrão - use-o para lidar com valores de seleção não planejados.
  • Para otimizar o desempenho, mova as ramificações do código com as escolhas mais comuns para o início do bloco switch.
  • Não se deixe levar pela “otimização” removendo a quebra no final do bloco de seleção de caso - esse código é difícil de entender e, como resultado, difícil de manter durante seu desenvolvimento.
Comentários
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION