Por que o compilador não coloca automaticamente as instruções break após cada bloco de código no switch? É por razões históricas? Quando você deseja que vários blocos de código sejam executados?
94
Por que o compilador não coloca automaticamente as instruções break após cada bloco de código no switch? É por razões históricas? Quando você deseja que vários blocos de código sejam executados?
break
.Respostas:
Às vezes é útil ter vários casos associados ao mesmo bloco de código, como
etc. Apenas um exemplo.
Na minha experiência, geralmente é um estilo ruim "falhar" e ter vários blocos de código executados para um caso, mas pode haver usos para isso em algumas situações.
fonte
// Intentional fallthrough.
ao omitir uma pausa. Não é tanto um estilo ruim quanto "fácil de esquecer uma pausa acidentalmente" na minha opinião. PS Claro que não em casos simples como na própria resposta.case
s estivessem empilhados dessa forma. Se houver código entre eles, então sim, o comentário provavelmente é válido.case
, assimcase 'A','B','C': doSomething(); case 'D','E': doSomethingElse();
:, sem precisar de uma pausa entre os casos. Pascal poderia fazer isso: "A instrução case compara o valor da expressão ordinal a cada seletor, que pode ser uma constante, um subintervalo ou uma lista deles separados por vírgulas." ( wiki.freepascal.org/Case )Historicamente , é porque o
case
estava essencialmente definindo umlabel
, também conhecido como o ponto-alvo de umagoto
chamada. A instrução switch e seus casos associados representam apenas uma ramificação de múltiplas vias com vários pontos de entrada potenciais em um fluxo de código.Dito isso, foi observado um número quase infinito de vezes que
break
quase sempre é o comportamento padrão que você prefere ter no final de cada caso.fonte
Java vem de C e essa é a sintaxe de C.
Há momentos em que você deseja que várias instruções de caso tenham apenas um caminho de execução. Abaixo está um exemplo que dirá quantos dias em um mês.
fonte
Eu acho que é um erro. Como uma construção de linguagem é tão fácil de ter
break
quanto o padrão e, em vez disso, ter umafallthrough
palavra - chave. A maior parte do código que escrevi e li tem uma pausa após cada caso.fonte
continue <case name>
que permite especificar explicitamente com qual instrução de caso continuar;case
dentro da correnteswitch
, isso simplesmente se torna umgoto
. ;-)Você pode fazer todo tipo de coisa interessante com o caso de falha.
Por exemplo, digamos que você queira fazer uma ação específica para todos os casos, mas em um determinado caso você deseja fazer essa ação mais alguma outra coisa. Usar uma instrução switch com fall-through tornaria isso muito fácil.
Obviamente, é fácil esquecer a
break
declaração no final de um caso e causar um comportamento inesperado. Bons compiladores irão avisá-lo quando você omitir a instrução break.fonte
Deixando de lado a boa vontade de poder usar o bloco idêntico para vários casos (que poderiam ser especiais) ...
É principalmente para compatibilidade com C, e é indiscutivelmente um hack antigo dos tempos antigos, quando as
goto
palavras-chave vagavam pela terra. Ele faz permitir que algumas coisas surpreendentes, é claro, como o dispositivo de Duff , mas se isso é um ponto a seu favor ou contra é ... argumentativa na melhor das hipóteses.fonte
O
break
switch posteriorcase
s é usado para evitar a queda nas instruções switch. Embora seja interessante, isso agora pode ser alcançado por meio dos rótulos de switch recém-formados, implementados via JEP-325 .Com essas mudanças, o
break
com cada trocacase
pode ser evitado conforme demonstrado mais adiante: -Ao executar o código acima com JDK-12 , a saída comparativa pode ser vista como
e
e, claro, a coisa inalterada
fonte
Portanto, você não precisa repetir o código se precisar de vários casos para fazer a mesma coisa:
Ou você pode fazer coisas como:
Em forma de cascata.
Muito sujeito a erros / confusão, se você me perguntar.
fonte
do this
edo that
para isso, mas apenasdo that
para isso?No que diz respeito ao registro histórico, Tony Hoare inventou a declaração do caso na década de 1960, durante a revolução da "programação estruturada". A declaração de caso de Tony suportava vários rótulos por caso e saída automática sem
break
declarações fedorentas . A exigência de um explícitobreak
foi algo que saiu da linha BCPL / B / C. Dennis Ritchie escreve (em ACM HOPL-II):Não consegui encontrar nenhum escrito histórico sobre a BCPL, mas o comentário de Ritchie sugere que
break
foi mais ou menos um acidente histórico. O BCPL mais tarde corrigiu o problema, mas talvez Ritchie e Thompson estivessem ocupados demais inventando o Unix para se incomodar com tal detalhe :-)fonte
break
permite "executar vários blocos de código", e está mais preocupado com a motivação dessa escolha de design. Outros mencionaram a herança bem conhecida do C ao Java, e essa resposta empurrou a pesquisa ainda mais para os dias anteriores ao C. Eu gostaria que tivéssemos esse padrão (embora muito primitivo) correspondendo desde o início.Java é derivado de C, cuja herança inclui uma técnica conhecida como Dispositivo de Duff . É uma otimização que depende do fato de que o controle cai de um caso para o outro, na ausência de uma
break;
instrução. Na época em que C foi padronizado, havia muito código como aquele "em liberdade", e teria sido contraproducente alterar a linguagem para quebrar tais construções.fonte
Como já se disse antes, é para permitir falhas e não é um erro, é uma característica. Se muitas
break
declarações o incomodam, você pode facilmente se livrar delas usando asreturn
declarações. Na verdade, esta é uma boa prática, porque seus métodos devem ser os menores possíveis (por uma questão de legibilidade e manutenção), então umaswitch
instrução já é grande o suficiente para um método, portanto, um bom método não deve conter nada mais, isso é um exemplo:A execução imprime:
como esperado.
fonte
Não ter uma interrupção automática adicionada pelo compilador torna possível usar uma opção / caso para testar as condições, como
1 <= a <= 3
remover a instrução break de 1 e 2.fonte
porque há situações em que você deseja fluir através do primeiro bloco, por exemplo, para evitar escrever o mesmo código em vários blocos, mas ainda ser capaz de dividi-los para controle mroe. Existem também muitos outros motivos.
fonte
É uma pergunta antiga, mas na verdade eu me deparei com a instrução case without break hoje. Na verdade, não usar break é muito útil quando você precisa combinar diferentes funções em sequência.
por exemplo, usando códigos de resposta http para autenticar o usuário com token de tempo
código de resposta do servidor 401 - token desatualizado -> regenerar token e fazer login do usuário.
código de resposta do servidor 200 - token está OK -> fazer login do usuário.
em declarações de caso:
Usando isso, você não precisa chamar a função de usuário de log para a resposta 401 porque quando o token é regenerado, o tempo de execução pula para o caso 200.
fonte
Você pode fazer facilmente separar outro tipo de número, mês, contagem.
Isso é melhor do que neste caso;
fonte
Agora estou trabalhando em um projeto do qual preciso,
break
em minha instrução switch, caso contrário, o código não funcionará. Tenha paciência comigo e eu darei um bom exemplo de por que você precisabreak
em sua declaração switch.Imagine que você tenha três estados, um que espera que o usuário insira um número, o segundo para calculá-lo e o terceiro para imprimir a soma.
Nesse caso, você tem:
Olhando para os estados, você gostaria que a ordem de exação começasse no estado1 , depois no estado3 e finalmente no estado2 . Caso contrário, imprimiremos apenas as entradas dos usuários sem calcular a soma. Só para esclarecer novamente, esperamos que o usuário insira um valor, então calculamos a soma e imprime a soma.
Aqui está um exemplo de código:
Se não usarmos
break
, ele será executado nesta ordem, estado1 , estado2 e estado3 . Mas usandobreak
, evitamos este cenário e podemos solicitar o procedimento correto que deve começar com o estado1, depois o estado3 e, por último, mas não menos importante, o estado2.fonte
Exatamente, porque com algum posicionamento inteligente você pode executar blocos em cascata.
fonte