As instruções de alternância com String
casos foram implementadas no Java SE 7 , pelo menos 16 anos após a primeira solicitação. Um motivo claro para o atraso não foi fornecido, mas provavelmente tinha a ver com desempenho.
Implementação no JDK 7
O recurso agora foi implementado javac
com um processo de "remoção de açúcar"; uma sintaxe limpa e de alto nível usando String
constantes nas case
declarações é expandida no tempo de compilação para um código mais complexo, seguindo um padrão. O código resultante usa instruções da JVM que sempre existiram.
A switch
com String
casos é convertido em dois comutadores durante a compilação. A primeira mapeia cada sequência para um número inteiro único - sua posição no comutador original. Isso é feito ativando primeiro o código de hash do rótulo. O caso correspondente é uma if
instrução que testa a igualdade das cadeias de caracteres; se houver colisões no hash, o teste será em cascata if-else-if
. A segunda opção espelha isso no código-fonte original, mas substitui os rótulos das caixas pelas suas posições correspondentes. Esse processo de duas etapas facilita a preservação do controle de fluxo da chave original.
Comutadores na JVM
Para obter mais detalhes técnicos switch
, consulte a Especificação da JVM, na qual a compilação das instruções do switch é descrita. Em poucas palavras, existem duas instruções diferentes da JVM que podem ser usadas para um comutador, dependendo da escassez das constantes usadas pelos casos. Ambos dependem do uso de constantes inteiras para que cada caso seja executado com eficiência.
Se as constantes são densas, elas são usadas como um índice (após subtrair o valor mais baixo) em uma tabela de indicadores de instruções - a tableswitch
instrução.
Se as constantes forem escassas, uma pesquisa binária do caso correto é executada - a lookupswitch
instrução.
Em de-adoçamento um switch
em String
objetos, ambas as instruções são susceptíveis de ser utilizados. A lookupswitch
é apropriado para o primeiro comutador de códigos de hash para encontrar a posição original do caso. O ordinal resultante é um ajuste natural para a tableswitch
.
Ambas as instruções exigem que as constantes inteiras atribuídas a cada caso sejam classificadas em tempo de compilação. Em tempo de execução, embora o O(1)
desempenho de tableswitch
geralmente pareça melhor que o O(log(n))
desempenho de lookupswitch
, ele requer alguma análise para determinar se a tabela é densa o suficiente para justificar a troca espaço-tempo. Bill Venners escreveu um ótimo artigo que aborda isso com mais detalhes, juntamente com uma análise detalhada de outras instruções de controle de fluxo Java.
Antes do JDK 7
Antes do JDK 7, enum
era possível aproximar um String
comutador baseado em. Isso usa ovalueOf
método estático gerado pelo compilador em todos os enum
tipos. Por exemplo:
Pill p = Pill.valueOf(str);
switch(p) {
case RED: pop(); break;
case BLUE: push(); break;
}